mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			530 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			530 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
// -*- C++ -*-
 | 
						|
 | 
						|
// Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 | 
						|
//
 | 
						|
// This file is part of the GNU ISO C++ Library.  This library is free
 | 
						|
// software; you can redistribute it and/or modify it under the terms
 | 
						|
// of the GNU General Public License as published by the Free Software
 | 
						|
// Foundation; either version 3, or (at your option) any later
 | 
						|
// version.
 | 
						|
 | 
						|
// This library is distributed in the hope that it will be useful, but
 | 
						|
// WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
// General Public License for more details.
 | 
						|
 | 
						|
// Under Section 7 of GPL version 3, you are granted additional
 | 
						|
// permissions described in the GCC Runtime Library Exception, version
 | 
						|
// 3.1, as published by the Free Software Foundation.
 | 
						|
 | 
						|
// You should have received a copy of the GNU General Public License and
 | 
						|
// a copy of the GCC Runtime Library Exception along with this program;
 | 
						|
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 | 
						|
// <http://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
/**
 | 
						|
 * @file parallel/set_operations.h
 | 
						|
 * @brief Parallel implementations of set operations for random-access
 | 
						|
 * iterators.
 | 
						|
 *  This file is a GNU parallel extension to the Standard C++ Library.
 | 
						|
 */
 | 
						|
 | 
						|
// Written by Marius Elvert and Felix Bondarenko.
 | 
						|
 | 
						|
#ifndef _GLIBCXX_PARALLEL_SET_OPERATIONS_H
 | 
						|
#define _GLIBCXX_PARALLEL_SET_OPERATIONS_H 1
 | 
						|
 | 
						|
#include <omp.h>
 | 
						|
 | 
						|
#include <parallel/settings.h>
 | 
						|
#include <parallel/multiseq_selection.h>
 | 
						|
 | 
						|
namespace __gnu_parallel
 | 
						|
{
 | 
						|
  template<typename _IIter, typename _OutputIterator>
 | 
						|
    _OutputIterator
 | 
						|
    __copy_tail(std::pair<_IIter, _IIter> __b,
 | 
						|
		std::pair<_IIter, _IIter> __e, _OutputIterator __r)
 | 
						|
    {
 | 
						|
      if (__b.first != __e.first)
 | 
						|
	{
 | 
						|
          do
 | 
						|
            {
 | 
						|
              *__r++ = *__b.first++;
 | 
						|
            }
 | 
						|
          while (__b.first != __e.first);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
          while (__b.second != __e.second)
 | 
						|
            *__r++ = *__b.second++;
 | 
						|
	}
 | 
						|
      return __r;
 | 
						|
    }
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Compare>
 | 
						|
    struct __symmetric_difference_func
 | 
						|
    {
 | 
						|
      typedef std::iterator_traits<_IIter> _TraitsType;
 | 
						|
      typedef typename _TraitsType::difference_type _DifferenceType;
 | 
						|
      typedef typename std::pair<_IIter, _IIter> _IteratorPair;
 | 
						|
 | 
						|
      __symmetric_difference_func(_Compare __comp) : _M_comp(__comp) {}
 | 
						|
 | 
						|
      _Compare _M_comp;
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
 | 
						|
		_OutputIterator __r) const
 | 
						|
      {
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              {
 | 
						|
        	*__r = *__a;
 | 
						|
        	++__a;
 | 
						|
        	++__r;
 | 
						|
              }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              {
 | 
						|
        	*__r = *__c;
 | 
						|
        	++__c;
 | 
						|
        	++__r;
 | 
						|
              }
 | 
						|
            else
 | 
						|
              {
 | 
						|
        	++__a;
 | 
						|
        	++__c;
 | 
						|
              }
 | 
						|
          }
 | 
						|
	return std::copy(__c, __d, std::copy(__a, __b, __r));
 | 
						|
      }
 | 
						|
 | 
						|
      _DifferenceType
 | 
						|
      __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
 | 
						|
      {
 | 
						|
	_DifferenceType __counter = 0;
 | 
						|
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              {
 | 
						|
        	++__a;
 | 
						|
        	++__counter;
 | 
						|
              }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              {
 | 
						|
        	++__c;
 | 
						|
        	++__counter;
 | 
						|
              }
 | 
						|
            else
 | 
						|
              {
 | 
						|
        	++__a;
 | 
						|
        	++__c;
 | 
						|
              }
 | 
						|
          }
 | 
						|
 | 
						|
	return __counter + (__b - __a) + (__d - __c);
 | 
						|
      }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const
 | 
						|
      { return std::copy(__c, __d, __out); }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
 | 
						|
      { return std::copy(__a, __b, __out); }
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Compare>
 | 
						|
    struct __difference_func
 | 
						|
    {
 | 
						|
      typedef std::iterator_traits<_IIter> _TraitsType;
 | 
						|
      typedef typename _TraitsType::difference_type _DifferenceType;
 | 
						|
      typedef typename std::pair<_IIter, _IIter> _IteratorPair;
 | 
						|
 | 
						|
      __difference_func(_Compare __comp) : _M_comp(__comp) {}
 | 
						|
 | 
						|
      _Compare _M_comp;
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
 | 
						|
		_OutputIterator __r) const
 | 
						|
      {
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              {
 | 
						|
        	*__r = *__a;
 | 
						|
        	++__a;
 | 
						|
        	++__r;
 | 
						|
              }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              { ++__c; }
 | 
						|
            else
 | 
						|
              {
 | 
						|
        	++__a;
 | 
						|
        	++__c;
 | 
						|
              }
 | 
						|
          }
 | 
						|
	return std::copy(__a, __b, __r);
 | 
						|
      }
 | 
						|
 | 
						|
      _DifferenceType
 | 
						|
      __count(_IIter __a, _IIter __b,
 | 
						|
	      _IIter __c, _IIter __d) const
 | 
						|
      {
 | 
						|
	_DifferenceType __counter = 0;
 | 
						|
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              {
 | 
						|
        	++__a;
 | 
						|
        	++__counter;
 | 
						|
              }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              { ++__c; }
 | 
						|
            else
 | 
						|
              { ++__a; ++__c; }
 | 
						|
          }
 | 
						|
 | 
						|
	return __counter + (__b - __a);
 | 
						|
      }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __first_empty(_IIter, _IIter, _OutputIterator __out) const
 | 
						|
      { return __out; }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
 | 
						|
      { return std::copy(__a, __b, __out); }
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Compare>
 | 
						|
    struct __intersection_func
 | 
						|
    {
 | 
						|
      typedef std::iterator_traits<_IIter> _TraitsType;
 | 
						|
      typedef typename _TraitsType::difference_type _DifferenceType;
 | 
						|
      typedef typename std::pair<_IIter, _IIter> _IteratorPair;
 | 
						|
 | 
						|
      __intersection_func(_Compare __comp) : _M_comp(__comp) {}
 | 
						|
 | 
						|
      _Compare _M_comp;
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d,
 | 
						|
		_OutputIterator __r) const
 | 
						|
      {
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              { ++__a; }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              { ++__c; }
 | 
						|
            else
 | 
						|
              {
 | 
						|
        	*__r = *__a;
 | 
						|
        	++__a;
 | 
						|
        	++__c;
 | 
						|
        	++__r;
 | 
						|
              }
 | 
						|
          }
 | 
						|
 | 
						|
	return __r;
 | 
						|
      }
 | 
						|
 | 
						|
      _DifferenceType
 | 
						|
      __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
 | 
						|
      {
 | 
						|
	_DifferenceType __counter = 0;
 | 
						|
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              { ++__a; }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              { ++__c; }
 | 
						|
            else
 | 
						|
              {
 | 
						|
        	++__a;
 | 
						|
        	++__c;
 | 
						|
        	++__counter;
 | 
						|
              }
 | 
						|
          }
 | 
						|
 | 
						|
	return __counter;
 | 
						|
      }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __first_empty(_IIter, _IIter, _OutputIterator __out) const
 | 
						|
      { return __out; }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __second_empty(_IIter, _IIter, _OutputIterator __out) const
 | 
						|
      { return __out; }
 | 
						|
    };
 | 
						|
 | 
						|
  template<class _IIter, class _OutputIterator, class _Compare>
 | 
						|
    struct __union_func
 | 
						|
    {
 | 
						|
      typedef typename std::iterator_traits<_IIter>::difference_type
 | 
						|
      _DifferenceType;
 | 
						|
 | 
						|
      __union_func(_Compare __comp) : _M_comp(__comp) {}
 | 
						|
 | 
						|
      _Compare _M_comp;
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      _M_invoke(_IIter __a, const _IIter __b, _IIter __c,
 | 
						|
		const _IIter __d, _OutputIterator __r) const
 | 
						|
      {
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              {
 | 
						|
        	*__r = *__a;
 | 
						|
        	++__a;
 | 
						|
              }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              {
 | 
						|
        	*__r = *__c;
 | 
						|
        	++__c;
 | 
						|
              }
 | 
						|
            else
 | 
						|
              {
 | 
						|
        	*__r = *__a;
 | 
						|
        	++__a;
 | 
						|
        	++__c;
 | 
						|
              }
 | 
						|
            ++__r;
 | 
						|
          }
 | 
						|
	return std::copy(__c, __d, std::copy(__a, __b, __r));
 | 
						|
      }
 | 
						|
 | 
						|
      _DifferenceType
 | 
						|
      __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const
 | 
						|
      {
 | 
						|
	_DifferenceType __counter = 0;
 | 
						|
 | 
						|
	while (__a != __b && __c != __d)
 | 
						|
          {
 | 
						|
            if (_M_comp(*__a, *__c))
 | 
						|
              { ++__a; }
 | 
						|
            else if (_M_comp(*__c, *__a))
 | 
						|
              { ++__c; }
 | 
						|
            else
 | 
						|
              {
 | 
						|
        	++__a;
 | 
						|
        	++__c;
 | 
						|
              }
 | 
						|
            ++__counter;
 | 
						|
          }
 | 
						|
 | 
						|
	__counter += (__b - __a);
 | 
						|
	__counter += (__d - __c);
 | 
						|
	return __counter;
 | 
						|
      }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const
 | 
						|
      { return std::copy(__c, __d, __out); }
 | 
						|
 | 
						|
      _OutputIterator
 | 
						|
      __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const
 | 
						|
      { return std::copy(__a, __b, __out); }
 | 
						|
    };
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Operation>
 | 
						|
    _OutputIterator
 | 
						|
    __parallel_set_operation(_IIter __begin1, _IIter __end1,
 | 
						|
			     _IIter __begin2, _IIter __end2,
 | 
						|
			     _OutputIterator __result, _Operation __op)
 | 
						|
    {
 | 
						|
      _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2))
 | 
						|
 | 
						|
      typedef std::iterator_traits<_IIter> _TraitsType;
 | 
						|
      typedef typename _TraitsType::difference_type _DifferenceType;
 | 
						|
      typedef typename std::pair<_IIter, _IIter> _IteratorPair;
 | 
						|
 | 
						|
      if (__begin1 == __end1)
 | 
						|
	return __op.__first_empty(__begin2, __end2, __result);
 | 
						|
 | 
						|
      if (__begin2 == __end2)
 | 
						|
	return __op.__second_empty(__begin1, __end1, __result);
 | 
						|
 | 
						|
      const _DifferenceType __size = (__end1 - __begin1) + (__end2 - __begin2);
 | 
						|
 | 
						|
      const _IteratorPair __sequence[2] = { std::make_pair(__begin1, __end1),
 | 
						|
					    std::make_pair(__begin2, __end2) };
 | 
						|
      _OutputIterator __return_value = __result;
 | 
						|
      _DifferenceType *__borders;
 | 
						|
      _IteratorPair *__block_begins;
 | 
						|
      _DifferenceType* __lengths;
 | 
						|
 | 
						|
      _ThreadIndex __num_threads =
 | 
						|
          std::min<_DifferenceType>(__get_max_threads(),
 | 
						|
              std::min(__end1 - __begin1, __end2 - __begin2));
 | 
						|
 | 
						|
#     pragma omp parallel num_threads(__num_threads)
 | 
						|
      {
 | 
						|
#       pragma omp single
 | 
						|
	{
 | 
						|
	  __num_threads = omp_get_num_threads();
 | 
						|
 | 
						|
	  __borders = new _DifferenceType[__num_threads + 2];
 | 
						|
	  __equally_split(__size, __num_threads + 1, __borders);
 | 
						|
	  __block_begins = new _IteratorPair[__num_threads + 1];
 | 
						|
	  // Very __start.
 | 
						|
	  __block_begins[0] = std::make_pair(__begin1, __begin2);
 | 
						|
	  __lengths = new _DifferenceType[__num_threads];
 | 
						|
	} //single
 | 
						|
 | 
						|
	_ThreadIndex __iam = omp_get_thread_num();
 | 
						|
 | 
						|
	// _Result from multiseq_partition.
 | 
						|
	_IIter __offset[2];
 | 
						|
	const _DifferenceType __rank = __borders[__iam + 1];
 | 
						|
 | 
						|
	multiseq_partition(__sequence, __sequence + 2,
 | 
						|
			   __rank, __offset, __op._M_comp);
 | 
						|
 | 
						|
	// allowed to read?
 | 
						|
	// together
 | 
						|
	// *(__offset[ 0 ] - 1) == *__offset[ 1 ]
 | 
						|
	if (__offset[ 0 ] != __begin1 && __offset[1] != __end2
 | 
						|
	    && !__op._M_comp(*(__offset[0] - 1), *__offset[1])
 | 
						|
	    && !__op._M_comp(*__offset[1], *(__offset[0] - 1)))
 | 
						|
	  {
 | 
						|
	    // Avoid split between globally equal elements: move one to
 | 
						|
	    // front in first sequence.
 | 
						|
              --__offset[0];
 | 
						|
	  }
 | 
						|
 | 
						|
	_IteratorPair __block_end = __block_begins[__iam + 1] =
 | 
						|
	  _IteratorPair(__offset[0], __offset[1]);
 | 
						|
 | 
						|
	// Make sure all threads have their block_begin result written out.
 | 
						|
#       pragma omp barrier
 | 
						|
 | 
						|
	_IteratorPair __block_begin = __block_begins[__iam];
 | 
						|
 | 
						|
	// Begin working for the first block, while the others except
 | 
						|
	// the last start to count.
 | 
						|
	if (__iam == 0)
 | 
						|
	  {
 | 
						|
	    // The first thread can copy already.
 | 
						|
	    __lengths[ __iam ] =
 | 
						|
	      __op._M_invoke(__block_begin.first, __block_end.first,
 | 
						|
			     __block_begin.second, __block_end.second,
 | 
						|
			     __result) - __result;
 | 
						|
	  }
 | 
						|
	else
 | 
						|
	  {
 | 
						|
	    __lengths[ __iam ] =
 | 
						|
	      __op.__count(__block_begin.first, __block_end.first,
 | 
						|
			   __block_begin.second, __block_end.second);
 | 
						|
	  }
 | 
						|
 | 
						|
	// Make sure everyone wrote their lengths.
 | 
						|
#       pragma omp barrier
 | 
						|
 | 
						|
	_OutputIterator __r = __result;
 | 
						|
 | 
						|
	if (__iam == 0)
 | 
						|
	  {
 | 
						|
	    // Do the last block.
 | 
						|
	    for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
 | 
						|
	      __r += __lengths[__i];
 | 
						|
 | 
						|
	    __block_begin = __block_begins[__num_threads];
 | 
						|
 | 
						|
	    // Return the result iterator of the last block.
 | 
						|
	    __return_value =
 | 
						|
	      __op._M_invoke(__block_begin.first, __end1,
 | 
						|
			     __block_begin.second, __end2, __r);
 | 
						|
 | 
						|
	  }
 | 
						|
          else
 | 
						|
            {
 | 
						|
              for (_ThreadIndex __i = 0; __i < __iam; ++__i)
 | 
						|
        	__r += __lengths[ __i ];
 | 
						|
 | 
						|
              // Reset begins for copy pass.
 | 
						|
              __op._M_invoke(__block_begin.first, __block_end.first,
 | 
						|
			     __block_begin.second, __block_end.second, __r);
 | 
						|
            }
 | 
						|
	}
 | 
						|
      return __return_value;
 | 
						|
    }
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Compare>
 | 
						|
    inline _OutputIterator
 | 
						|
    __parallel_set_union(_IIter __begin1, _IIter __end1,
 | 
						|
			 _IIter __begin2, _IIter __end2,
 | 
						|
			 _OutputIterator __result, _Compare __comp)
 | 
						|
    {
 | 
						|
      return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
 | 
						|
				      __result,
 | 
						|
				      __union_func< _IIter, _OutputIterator,
 | 
						|
				      _Compare>(__comp));
 | 
						|
    }
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Compare>
 | 
						|
    inline _OutputIterator
 | 
						|
    __parallel_set_intersection(_IIter __begin1, _IIter __end1,
 | 
						|
                        	_IIter __begin2, _IIter __end2,
 | 
						|
                        	_OutputIterator __result, _Compare __comp)
 | 
						|
    {
 | 
						|
      return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
 | 
						|
				      __result,
 | 
						|
				      __intersection_func<_IIter,
 | 
						|
				      _OutputIterator, _Compare>(__comp));
 | 
						|
    }
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Compare>
 | 
						|
    inline _OutputIterator
 | 
						|
    __parallel_set_difference(_IIter __begin1, _IIter __end1,
 | 
						|
                              _IIter __begin2, _IIter __end2,
 | 
						|
                              _OutputIterator __result, _Compare __comp)
 | 
						|
    {
 | 
						|
      return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
 | 
						|
				      __result,
 | 
						|
				      __difference_func<_IIter,
 | 
						|
				      _OutputIterator, _Compare>(__comp));
 | 
						|
    }
 | 
						|
 | 
						|
  template<typename _IIter,
 | 
						|
           typename _OutputIterator,
 | 
						|
           typename _Compare>
 | 
						|
    inline _OutputIterator
 | 
						|
    __parallel_set_symmetric_difference(_IIter __begin1, _IIter __end1,
 | 
						|
                                	_IIter __begin2, _IIter __end2,
 | 
						|
                                	_OutputIterator __result,
 | 
						|
                                	_Compare __comp)
 | 
						|
    {
 | 
						|
      return __parallel_set_operation(__begin1, __end1, __begin2, __end2,
 | 
						|
				      __result,
 | 
						|
				      __symmetric_difference_func<_IIter,
 | 
						|
				      _OutputIterator, _Compare>(__comp));
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#endif /* _GLIBCXX_PARALLEL_SET_OPERATIONS_H */
 |