mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			530 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			530 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
| // -*- C++ -*-
 | |
| 
 | |
| // Copyright (C) 2007-2016 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 */
 |