Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // -*- C++ -*-
  2.  
  3. // Copyright (C) 2007-2015 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. /**
  26.  * @file parallel/set_operations.h
  27.  * @brief Parallel implementations of set operations for random-access
  28.  * iterators.
  29.  *  This file is a GNU parallel extension to the Standard C++ Library.
  30.  */
  31.  
  32. // Written by Marius Elvert and Felix Bondarenko.
  33.  
  34. #ifndef _GLIBCXX_PARALLEL_SET_OPERATIONS_H
  35. #define _GLIBCXX_PARALLEL_SET_OPERATIONS_H 1
  36.  
  37. #include <omp.h>
  38.  
  39. #include <parallel/settings.h>
  40. #include <parallel/multiseq_selection.h>
  41.  
  42. namespace __gnu_parallel
  43. {
  44.   template<typename _IIter, typename _OutputIterator>
  45.     _OutputIterator
  46.     __copy_tail(std::pair<_IIter, _IIter> __b,
  47.                 std::pair<_IIter, _IIter> __e, _OutputIterator __r)
  48.     {
  49.       if (__b.first != __e.first)
  50.         {
  51.           do
  52.             {
  53.               *__r++ = *__b.first++;
  54.             }
  55.           while (__b.first != __e.first);
  56.         }
  57.       else
  58.         {
  59.           while (__b.second != __e.second)
  60.             *__r++ = *__b.second++;
  61.         }
  62.       return __r;
  63.     }
  64.  
  65.   template<typename _IIter,
  66.            typename _OutputIterator,
  67.            typename _Compare>
  68.     struct __symmetric_difference_func
  69.     {
  70.       typedef std::iterator_traits<_IIter> _TraitsType;
  71.       typedef typename _TraitsType::difference_type _DifferenceType;
  72.       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
  73.  
  74.       __symmetric_difference_func(_Compare __comp) : _M_comp(__comp) {}
  75.  
  76.       _Compare _M_comp;
  77.  
  78.       _OutputIterator
  79.       _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
  80.                 _OutputIterator __r) const
  81.       {
  82.         while (__a != __b && __c != __d)
  83.           {
  84.             if (_M_comp(*__a, *__c))
  85.               {
  86.                 *__r = *__a;
  87.                 ++__a;
  88.                 ++__r;
  89.               }
  90.             else if (_M_comp(*__c, *__a))
  91.               {
  92.                 *__r = *__c;
  93.                 ++__c;
  94.                 ++__r;
  95.               }
  96.             else
  97.               {
  98.                 ++__a;
  99.                 ++__c;
  100.               }
  101.           }
  102.         return std::copy(__c, __d, std::copy(__a, __b, __r));
  103.       }
  104.  
  105.       _DifferenceType
  106.       __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
  107.       {
  108.         _DifferenceType __counter = 0;
  109.  
  110.         while (__a != __b && __c != __d)
  111.           {
  112.             if (_M_comp(*__a, *__c))
  113.               {
  114.                 ++__a;
  115.                 ++__counter;
  116.               }
  117.             else if (_M_comp(*__c, *__a))
  118.               {
  119.                 ++__c;
  120.                 ++__counter;
  121.               }
  122.             else
  123.               {
  124.                 ++__a;
  125.                 ++__c;
  126.               }
  127.           }
  128.  
  129.         return __counter + (__b - __a) + (__d - __c);
  130.       }
  131.  
  132.       _OutputIterator
  133.       __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const
  134.       { return std::copy(__c, __d, __out); }
  135.  
  136.       _OutputIterator
  137.       __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
  138.       { return std::copy(__a, __b, __out); }
  139.     };
  140.  
  141.  
  142.   template<typename _IIter,
  143.            typename _OutputIterator,
  144.            typename _Compare>
  145.     struct __difference_func
  146.     {
  147.       typedef std::iterator_traits<_IIter> _TraitsType;
  148.       typedef typename _TraitsType::difference_type _DifferenceType;
  149.       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
  150.  
  151.       __difference_func(_Compare __comp) : _M_comp(__comp) {}
  152.  
  153.       _Compare _M_comp;
  154.  
  155.       _OutputIterator
  156.       _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
  157.                 _OutputIterator __r) const
  158.       {
  159.         while (__a != __b && __c != __d)
  160.           {
  161.             if (_M_comp(*__a, *__c))
  162.               {
  163.                 *__r = *__a;
  164.                 ++__a;
  165.                 ++__r;
  166.               }
  167.             else if (_M_comp(*__c, *__a))
  168.               { ++__c; }
  169.             else
  170.               {
  171.                 ++__a;
  172.                 ++__c;
  173.               }
  174.           }
  175.         return std::copy(__a, __b, __r);
  176.       }
  177.  
  178.       _DifferenceType
  179.       __count(_IIter __a, _IIter __b,
  180.               _IIter __c, _IIter __d) const
  181.       {
  182.         _DifferenceType __counter = 0;
  183.  
  184.         while (__a != __b && __c != __d)
  185.           {
  186.             if (_M_comp(*__a, *__c))
  187.               {
  188.                 ++__a;
  189.                 ++__counter;
  190.               }
  191.             else if (_M_comp(*__c, *__a))
  192.               { ++__c; }
  193.             else
  194.               { ++__a; ++__c; }
  195.           }
  196.  
  197.         return __counter + (__b - __a);
  198.       }
  199.  
  200.       _OutputIterator
  201.       __first_empty(_IIter, _IIter, _OutputIterator __out) const
  202.       { return __out; }
  203.  
  204.       _OutputIterator
  205.       __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
  206.       { return std::copy(__a, __b, __out); }
  207.     };
  208.  
  209.  
  210.   template<typename _IIter,
  211.            typename _OutputIterator,
  212.            typename _Compare>
  213.     struct __intersection_func
  214.     {
  215.       typedef std::iterator_traits<_IIter> _TraitsType;
  216.       typedef typename _TraitsType::difference_type _DifferenceType;
  217.       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
  218.  
  219.       __intersection_func(_Compare __comp) : _M_comp(__comp) {}
  220.  
  221.       _Compare _M_comp;
  222.  
  223.       _OutputIterator
  224.       _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
  225.                 _OutputIterator __r) const
  226.       {
  227.         while (__a != __b && __c != __d)
  228.           {
  229.             if (_M_comp(*__a, *__c))
  230.               { ++__a; }
  231.             else if (_M_comp(*__c, *__a))
  232.               { ++__c; }
  233.             else
  234.               {
  235.                 *__r = *__a;
  236.                 ++__a;
  237.                 ++__c;
  238.                 ++__r;
  239.               }
  240.           }
  241.  
  242.         return __r;
  243.       }
  244.  
  245.       _DifferenceType
  246.       __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
  247.       {
  248.         _DifferenceType __counter = 0;
  249.  
  250.         while (__a != __b && __c != __d)
  251.           {
  252.             if (_M_comp(*__a, *__c))
  253.               { ++__a; }
  254.             else if (_M_comp(*__c, *__a))
  255.               { ++__c; }
  256.             else
  257.               {
  258.                 ++__a;
  259.                 ++__c;
  260.                 ++__counter;
  261.               }
  262.           }
  263.  
  264.         return __counter;
  265.       }
  266.  
  267.       _OutputIterator
  268.       __first_empty(_IIter, _IIter, _OutputIterator __out) const
  269.       { return __out; }
  270.  
  271.       _OutputIterator
  272.       __second_empty(_IIter, _IIter, _OutputIterator __out) const
  273.       { return __out; }
  274.     };
  275.  
  276.   template<class _IIter, class _OutputIterator, class _Compare>
  277.     struct __union_func
  278.     {
  279.       typedef typename std::iterator_traits<_IIter>::difference_type
  280.       _DifferenceType;
  281.  
  282.       __union_func(_Compare __comp) : _M_comp(__comp) {}
  283.  
  284.       _Compare _M_comp;
  285.  
  286.       _OutputIterator
  287.       _M_invoke(_IIter __a, const _IIter __b, _IIter __c,
  288.                 const _IIter __d, _OutputIterator __r) const
  289.       {
  290.         while (__a != __b && __c != __d)
  291.           {
  292.             if (_M_comp(*__a, *__c))
  293.               {
  294.                 *__r = *__a;
  295.                 ++__a;
  296.               }
  297.             else if (_M_comp(*__c, *__a))
  298.               {
  299.                 *__r = *__c;
  300.                 ++__c;
  301.               }
  302.             else
  303.               {
  304.                 *__r = *__a;
  305.                 ++__a;
  306.                 ++__c;
  307.               }
  308.             ++__r;
  309.           }
  310.         return std::copy(__c, __d, std::copy(__a, __b, __r));
  311.       }
  312.  
  313.       _DifferenceType
  314.       __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
  315.       {
  316.         _DifferenceType __counter = 0;
  317.  
  318.         while (__a != __b && __c != __d)
  319.           {
  320.             if (_M_comp(*__a, *__c))
  321.               { ++__a; }
  322.             else if (_M_comp(*__c, *__a))
  323.               { ++__c; }
  324.             else
  325.               {
  326.                 ++__a;
  327.                 ++__c;
  328.               }
  329.             ++__counter;
  330.           }
  331.  
  332.         __counter += (__b - __a);
  333.         __counter += (__d - __c);
  334.         return __counter;
  335.       }
  336.  
  337.       _OutputIterator
  338.       __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const
  339.       { return std::copy(__c, __d, __out); }
  340.  
  341.       _OutputIterator
  342.       __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
  343.       { return std::copy(__a, __b, __out); }
  344.     };
  345.  
  346.   template<typename _IIter,
  347.            typename _OutputIterator,
  348.            typename _Operation>
  349.     _OutputIterator
  350.     __parallel_set_operation(_IIter __begin1, _IIter __end1,
  351.                              _IIter __begin2, _IIter __end2,
  352.                              _OutputIterator __result, _Operation __op)
  353.     {
  354.       _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2))
  355.  
  356.       typedef std::iterator_traits<_IIter> _TraitsType;
  357.       typedef typename _TraitsType::difference_type _DifferenceType;
  358.       typedef typename std::pair<_IIter, _IIter> _IteratorPair;
  359.  
  360.       if (__begin1 == __end1)
  361.         return __op.__first_empty(__begin2, __end2, __result);
  362.  
  363.       if (__begin2 == __end2)
  364.         return __op.__second_empty(__begin1, __end1, __result);
  365.  
  366.       const _DifferenceType __size = (__end1 - __begin1) + (__end2 - __begin2);
  367.  
  368.       const _IteratorPair __sequence[2] = { std::make_pair(__begin1, __end1),
  369.                                             std::make_pair(__begin2, __end2) };
  370.       _OutputIterator __return_value = __result;
  371.       _DifferenceType *__borders;
  372.       _IteratorPair *__block_begins;
  373.       _DifferenceType* __lengths;
  374.  
  375.       _ThreadIndex __num_threads =
  376.           std::min<_DifferenceType>(__get_max_threads(),
  377.               std::min(__end1 - __begin1, __end2 - __begin2));
  378.  
  379. #     pragma omp parallel num_threads(__num_threads)
  380.       {
  381. #       pragma omp single
  382.         {
  383.           __num_threads = omp_get_num_threads();
  384.  
  385.           __borders = new _DifferenceType[__num_threads + 2];
  386.           __equally_split(__size, __num_threads + 1, __borders);
  387.           __block_begins = new _IteratorPair[__num_threads + 1];
  388.           // Very __start.
  389.           __block_begins[0] = std::make_pair(__begin1, __begin2);
  390.           __lengths = new _DifferenceType[__num_threads];
  391.         } //single
  392.  
  393.         _ThreadIndex __iam = omp_get_thread_num();
  394.  
  395.         // _Result from multiseq_partition.
  396.         _IIter __offset[2];
  397.         const _DifferenceType __rank = __borders[__iam + 1];
  398.  
  399.         multiseq_partition(__sequence, __sequence + 2,
  400.                            __rank, __offset, __op._M_comp);
  401.  
  402.         // allowed to read?
  403.         // together
  404.         // *(__offset[ 0 ] - 1) == *__offset[ 1 ]
  405.         if (__offset[ 0 ] != __begin1 && __offset[1] != __end2
  406.             && !__op._M_comp(*(__offset[0] - 1), *__offset[1])
  407.             && !__op._M_comp(*__offset[1], *(__offset[0] - 1)))
  408.           {
  409.             // Avoid split between globally equal elements: move one to
  410.             // front in first sequence.
  411.               --__offset[0];
  412.           }
  413.  
  414.         _IteratorPair __block_end = __block_begins[__iam + 1] =
  415.           _IteratorPair(__offset[0], __offset[1]);
  416.  
  417.         // Make sure all threads have their block_begin result written out.
  418. #       pragma omp barrier
  419.  
  420.         _IteratorPair __block_begin = __block_begins[__iam];
  421.  
  422.         // Begin working for the first block, while the others except
  423.         // the last start to count.
  424.         if (__iam == 0)
  425.           {
  426.             // The first thread can copy already.
  427.             __lengths[ __iam ] =
  428.               __op._M_invoke(__block_begin.first, __block_end.first,
  429.                              __block_begin.second, __block_end.second,
  430.                              __result) - __result;
  431.           }
  432.         else
  433.           {
  434.             __lengths[ __iam ] =
  435.               __op.__count(__block_begin.first, __block_end.first,
  436.                            __block_begin.second, __block_end.second);
  437.           }
  438.  
  439.         // Make sure everyone wrote their lengths.
  440. #       pragma omp barrier
  441.  
  442.         _OutputIterator __r = __result;
  443.  
  444.         if (__iam == 0)
  445.           {
  446.             // Do the last block.
  447.             for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
  448.               __r += __lengths[__i];
  449.  
  450.             __block_begin = __block_begins[__num_threads];
  451.  
  452.             // Return the result iterator of the last block.
  453.             __return_value =
  454.               __op._M_invoke(__block_begin.first, __end1,
  455.                              __block_begin.second, __end2, __r);
  456.  
  457.           }
  458.           else
  459.             {
  460.               for (_ThreadIndex __i = 0; __i < __iam; ++__i)
  461.                 __r += __lengths[ __i ];
  462.  
  463.               // Reset begins for copy pass.
  464.               __op._M_invoke(__block_begin.first, __block_end.first,
  465.                              __block_begin.second, __block_end.second, __r);
  466.             }
  467.         }
  468.       return __return_value;
  469.     }
  470.  
  471.   template<typename _IIter,
  472.            typename _OutputIterator,
  473.            typename _Compare>
  474.     inline _OutputIterator
  475.     __parallel_set_union(_IIter __begin1, _IIter __end1,
  476.                          _IIter __begin2, _IIter __end2,
  477.                          _OutputIterator __result, _Compare __comp)
  478.     {
  479.       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
  480.                                       __result,
  481.                                       __union_func< _IIter, _OutputIterator,
  482.                                       _Compare>(__comp));
  483.     }
  484.  
  485.   template<typename _IIter,
  486.            typename _OutputIterator,
  487.            typename _Compare>
  488.     inline _OutputIterator
  489.     __parallel_set_intersection(_IIter __begin1, _IIter __end1,
  490.                                 _IIter __begin2, _IIter __end2,
  491.                                 _OutputIterator __result, _Compare __comp)
  492.     {
  493.       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
  494.                                       __result,
  495.                                       __intersection_func<_IIter,
  496.                                       _OutputIterator, _Compare>(__comp));
  497.     }
  498.  
  499.   template<typename _IIter,
  500.            typename _OutputIterator,
  501.            typename _Compare>
  502.     inline _OutputIterator
  503.     __parallel_set_difference(_IIter __begin1, _IIter __end1,
  504.                               _IIter __begin2, _IIter __end2,
  505.                               _OutputIterator __result, _Compare __comp)
  506.     {
  507.       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
  508.                                       __result,
  509.                                       __difference_func<_IIter,
  510.                                       _OutputIterator, _Compare>(__comp));
  511.     }
  512.  
  513.   template<typename _IIter,
  514.            typename _OutputIterator,
  515.            typename _Compare>
  516.     inline _OutputIterator
  517.     __parallel_set_symmetric_difference(_IIter __begin1, _IIter __end1,
  518.                                         _IIter __begin2, _IIter __end2,
  519.                                         _OutputIterator __result,
  520.                                         _Compare __comp)
  521.     {
  522.       return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
  523.                                       __result,
  524.                                       __symmetric_difference_func<_IIter,
  525.                                       _OutputIterator, _Compare>(__comp));
  526.     }
  527. }
  528.  
  529. #endif /* _GLIBCXX_PARALLEL_SET_OPERATIONS_H */
  530.