Commit 338311e5 by Paolo Carlini Committed by Paolo Carlini

multiway_merge.h: Simple formatting and uglification fixes.

2009-11-05  Paolo Carlini  <paolo.carlini@oracle.com>

	* include/parallel/multiway_merge.h: Simple formatting and
	uglification fixes.
	* include/parallel/losertree.h: Likewise.
	* include/parallel/base.h: Likewise.
	* include/parallel/par_loop.h: Likewise.
	* include/parallel/omp_loop_static.h: Likewise.
	* include/parallel/multiway_mergesort.h: Likewise.
	* include/parallel/partial_sum.h: Likewise.
	* include/parallel/omp_loop.h: Likewise.

From-SVN: r153939
parent 94086ef6
2009-11-05 Paolo Carlini <paolo.carlini@oracle.com>
* include/parallel/multiway_merge.h: Simple formatting and
uglification fixes.
* include/parallel/losertree.h: Likewise.
* include/parallel/base.h: Likewise.
* include/parallel/par_loop.h: Likewise.
* include/parallel/omp_loop_static.h: Likewise.
* include/parallel/multiway_mergesort.h: Likewise.
* include/parallel/partial_sum.h: Likewise.
* include/parallel/omp_loop.h: Likewise.
2009-11-04 Benjamin Kosnik <bkoz@redhat.com> 2009-11-04 Benjamin Kosnik <bkoz@redhat.com>
* testsuite/25_algorithms/fill/5.cc: Move... * testsuite/25_algorithms/fill/5.cc: Move...
......
...@@ -93,13 +93,13 @@ namespace __gnu_parallel ...@@ -93,13 +93,13 @@ namespace __gnu_parallel
__is_parallel(const _Parallelism __p) { return __p != sequential; } __is_parallel(const _Parallelism __p) { return __p != sequential; }
/** @brief Calculates the rounded-down logarithm of @__c __n for base 2. /** @brief Calculates the rounded-down logarithm of @__c __n for base 2.
* @param __n Argument. * @param __n Argument.
* @return Returns 0 for any argument <1. * @return Returns 0 for any argument <1.
*/ */
template<typename _Size> template<typename _Size>
inline _Size inline _Size
__rd_log2(_Size __n) __rd_log2(_Size __n)
{ {
_Size __k; _Size __k;
for (__k = 0; __n > 1; __n >>= 1) for (__k = 0; __n > 1; __n >>= 1)
...@@ -107,356 +107,352 @@ template<typename _Size> ...@@ -107,356 +107,352 @@ template<typename _Size>
return __k; return __k;
} }
/** @brief Encode two integers into one gnu_parallel::_CASable. /** @brief Encode two integers into one gnu_parallel::_CASable.
* @param __a First integer, to be encoded in the most-significant @__c * @param __a First integer, to be encoded in the most-significant @__c
* _CASable_bits/2 bits. * _CASable_bits/2 bits.
* @param __b Second integer, to be encoded in the least-significant * @param __b Second integer, to be encoded in the least-significant
* @__c _CASable_bits/2 bits. * @__c _CASable_bits/2 bits.
* @return value encoding @__c __a and @__c __b. * @return value encoding @__c __a and @__c __b.
* @see decode2 * @see decode2
*/ */
inline _CASable inline _CASable
__encode2(int __a, int __b) //must all be non-negative, actually __encode2(int __a, int __b) //must all be non-negative, actually
{
return (((_CASable)__a) << (_CASable_bits / 2)) | (((_CASable)__b) << 0);
}
/** @brief Decode two integers from one gnu_parallel::_CASable.
* @param __x __gnu_parallel::_CASable to decode integers from.
* @param __a First integer, to be decoded from the most-significant
* @__c _CASable_bits/2 bits of @__c __x.
* @param __b Second integer, to be encoded in the least-significant
* @__c _CASable_bits/2 bits of @__c __x.
* @see __encode2
*/
inline void
decode2(_CASable __x, int& __a, int& __b)
{
__a = (int)((__x >> (_CASable_bits / 2)) & _CASable_mask);
__b = (int)((__x >> 0 ) & _CASable_mask);
}
//needed for parallel "numeric", even if "algorithm" not included
/** @brief Equivalent to std::min. */
template<typename _Tp>
const _Tp&
min(const _Tp& __a, const _Tp& __b)
{ return (__a < __b) ? __a : __b; }
/** @brief Equivalent to std::max. */
template<typename _Tp>
const _Tp&
max(const _Tp& __a, const _Tp& __b)
{ return (__a > __b) ? __a : __b; }
/** @brief Constructs predicate for equality from strict weak
* ordering predicate
*/
template<typename _T1, typename _T2, typename _Compare>
class _EqualFromLess : public std::binary_function<_T1, _T2, bool>
{ {
private: return (((_CASable)__a) << (_CASable_bits / 2)) | (((_CASable)__b) << 0);
_Compare& _M_comp; }
public: /** @brief Decode two integers from one gnu_parallel::_CASable.
_EqualFromLess(_Compare& __comp) : _M_comp(__comp) { } * @param __x __gnu_parallel::_CASable to decode integers from.
* @param __a First integer, to be decoded from the most-significant
* @__c _CASable_bits/2 bits of @__c __x.
* @param __b Second integer, to be encoded in the least-significant
* @__c _CASable_bits/2 bits of @__c __x.
* @see __encode2
*/
inline void
decode2(_CASable __x, int& __a, int& __b)
{
__a = (int)((__x >> (_CASable_bits / 2)) & _CASable_mask);
__b = (int)((__x >> 0 ) & _CASable_mask);
}
bool operator()(const _T1& __a, const _T2& __b) //needed for parallel "numeric", even if "algorithm" not included
{
return !_M_comp(__a, __b) && !_M_comp(__b, __a);
}
};
/** @brief Equivalent to std::min. */
template<typename _Tp>
const _Tp&
min(const _Tp& __a, const _Tp& __b)
{ return (__a < __b) ? __a : __b; }
/** @brief Similar to std::binder1st, /** @brief Equivalent to std::max. */
* but giving the argument types explicitly. */ template<typename _Tp>
template<typename _Predicate, typename argument_type> const _Tp&
class __unary_negate max(const _Tp& __a, const _Tp& __b)
: public std::unary_function<argument_type, bool> { return (__a > __b) ? __a : __b; }
{
protected: /** @brief Constructs predicate for equality from strict weak
_Predicate _M_pred; * ordering predicate
*/
public: template<typename _T1, typename _T2, typename _Compare>
explicit class _EqualFromLess : public std::binary_function<_T1, _T2, bool>
__unary_negate(const _Predicate& __x) : _M_pred(__x) { } {
private:
bool _Compare& _M_comp;
operator()(const argument_type& __x)
{ return !_M_pred(__x); }
};
/** @brief Similar to std::binder1st,
* but giving the argument types explicitly. */
template<typename _Operation, typename _FirstArgumentType,
typename _SecondArgumentType, typename _ResultType>
class __binder1st
: public std::unary_function<_SecondArgumentType, _ResultType>
{
protected:
_Operation _M_op;
_FirstArgumentType _M_value;
public:
__binder1st(const _Operation& __x,
const _FirstArgumentType& __y)
: _M_op(__x), _M_value(__y) { }
_ResultType
operator()(const _SecondArgumentType& __x)
{ return _M_op(_M_value, __x); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 109. Missing binders for non-const sequence elements
_ResultType
operator()(_SecondArgumentType& __x) const
{ return _M_op(_M_value, __x); }
};
/** public:
* @brief Similar to std::binder2nd, but giving the argument types _EqualFromLess(_Compare& __comp) : _M_comp(__comp) { }
* explicitly.
*/
template<typename _Operation, typename _FirstArgumentType,
typename _SecondArgumentType, typename _ResultType>
class binder2nd
: public std::unary_function<_FirstArgumentType, _ResultType>
{
protected:
_Operation _M_op;
_SecondArgumentType _M_value;
public:
binder2nd(const _Operation& __x,
const _SecondArgumentType& __y)
: _M_op(__x), _M_value(__y) { }
_ResultType
operator()(const _FirstArgumentType& __x) const
{ return _M_op(__x, _M_value); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 109. Missing binders for non-const sequence elements
_ResultType
operator()(_FirstArgumentType& __x)
{ return _M_op(__x, _M_value); }
};
/** @brief Similar to std::equal_to, but allows two different types. */
template<typename _T1, typename _T2>
struct _EqualTo : std::binary_function<_T1, _T2, bool>
{
bool operator()(const _T1& __t1, const _T2& __t2) const
{ return __t1 == __t2; }
};
/** @brief Similar to std::less, but allows two different types. */ bool operator()(const _T1& __a, const _T2& __b)
template<typename _T1, typename _T2> { return !_M_comp(__a, __b) && !_M_comp(__b, __a); }
struct _Less : std::binary_function<_T1, _T2, bool> };
{
bool
operator()(const _T1& __t1, const _T2& __t2) const
{ return __t1 < __t2; }
bool
operator()(const _T2& __t2, const _T1& __t1) const
{ return __t2 < __t1; }
};
// Partial specialization for one type. Same as std::less.
template<typename _Tp>
struct _Less<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x < __y; }
};
/** @brief Similar to std::plus, but allows two different types. */ /** @brief Similar to std::binder1st,
template<typename _Tp1, typename _Tp2> * but giving the argument types explicitly. */
struct _Plus : public std::binary_function<_Tp1, _Tp2, _Tp1> template<typename _Predicate, typename argument_type>
{ class __unary_negate
typedef __typeof__(*static_cast<_Tp1*>(NULL) : public std::unary_function<argument_type, bool>
+ *static_cast<_Tp2*>(NULL)) __result; {
protected:
_Predicate _M_pred;
public:
explicit
__unary_negate(const _Predicate& __x) : _M_pred(__x) { }
bool
operator()(const argument_type& __x)
{ return !_M_pred(__x); }
};
/** @brief Similar to std::binder1st,
* but giving the argument types explicitly. */
template<typename _Operation, typename _FirstArgumentType,
typename _SecondArgumentType, typename _ResultType>
class __binder1st
: public std::unary_function<_SecondArgumentType, _ResultType>
{
protected:
_Operation _M_op;
_FirstArgumentType _M_value;
public:
__binder1st(const _Operation& __x, const _FirstArgumentType& __y)
: _M_op(__x), _M_value(__y) { }
_ResultType
operator()(const _SecondArgumentType& __x)
{ return _M_op(_M_value, __x); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 109. Missing binders for non-const sequence elements
_ResultType
operator()(_SecondArgumentType& __x) const
{ return _M_op(_M_value, __x); }
};
/**
* @brief Similar to std::binder2nd, but giving the argument types
* explicitly.
*/
template<typename _Operation, typename _FirstArgumentType,
typename _SecondArgumentType, typename _ResultType>
class binder2nd
: public std::unary_function<_FirstArgumentType, _ResultType>
{
protected:
_Operation _M_op;
_SecondArgumentType _M_value;
public:
binder2nd(const _Operation& __x, const _SecondArgumentType& __y)
: _M_op(__x), _M_value(__y) { }
_ResultType
operator()(const _FirstArgumentType& __x) const
{ return _M_op(__x, _M_value); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 109. Missing binders for non-const sequence elements
_ResultType
operator()(_FirstArgumentType& __x)
{ return _M_op(__x, _M_value); }
};
/** @brief Similar to std::equal_to, but allows two different types. */
template<typename _T1, typename _T2>
struct _EqualTo : std::binary_function<_T1, _T2, bool>
{
bool operator()(const _T1& __t1, const _T2& __t2) const
{ return __t1 == __t2; }
};
__result /** @brief Similar to std::less, but allows two different types. */
operator()(const _Tp1& __x, const _Tp2& __y) const template<typename _T1, typename _T2>
{ return __x + __y; } struct _Less : std::binary_function<_T1, _T2, bool>
}; {
bool
operator()(const _T1& __t1, const _T2& __t2) const
{ return __t1 < __t2; }
bool
operator()(const _T2& __t2, const _T1& __t1) const
{ return __t2 < __t1; }
};
// Partial specialization for one type. Same as std::less.
template<typename _Tp>
struct _Less<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x < __y; }
};
// Partial specialization for one type. Same as std::plus.
template<typename _Tp>
struct _Plus<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, _Tp>
{
typedef __typeof__(*static_cast<_Tp*>(NULL)
+ *static_cast<_Tp*>(NULL)) __result;
__result /** @brief Similar to std::plus, but allows two different types. */
operator()(const _Tp& __x, const _Tp& __y) const template<typename _Tp1, typename _Tp2>
{ return __x + __y; } struct _Plus : public std::binary_function<_Tp1, _Tp2, _Tp1>
}; {
typedef __typeof__(*static_cast<_Tp1*>(NULL)
+ *static_cast<_Tp2*>(NULL)) __result;
__result
operator()(const _Tp1& __x, const _Tp2& __y) const
{ return __x + __y; }
};
/** @brief Similar to std::multiplies, but allows two different types. */ // Partial specialization for one type. Same as std::plus.
template<typename _Tp1, typename _Tp2> template<typename _Tp>
struct _Multiplies : public std::binary_function<_Tp1, _Tp2, _Tp1> struct _Plus<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, _Tp>
{ {
typedef __typeof__(*static_cast<_Tp1*>(NULL) typedef __typeof__(*static_cast<_Tp*>(NULL)
* *static_cast<_Tp2*>(NULL)) __result; + *static_cast<_Tp*>(NULL)) __result;
__result __result
operator()(const _Tp1& __x, const _Tp2& __y) const operator()(const _Tp& __x, const _Tp& __y) const
{ return __x * __y; } { return __x + __y; }
}; };
// Partial specialization for one type. Same as std::multiplies.
template<typename _Tp>
struct _Multiplies<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, _Tp>
{
typedef __typeof__(*static_cast<_Tp*>(NULL)
* *static_cast<_Tp*>(NULL)) __result;
__result /** @brief Similar to std::multiplies, but allows two different types. */
operator()(const _Tp& __x, const _Tp& __y) const template<typename _Tp1, typename _Tp2>
{ return __x * __y; } struct _Multiplies : public std::binary_function<_Tp1, _Tp2, _Tp1>
}; {
typedef __typeof__(*static_cast<_Tp1*>(NULL)
* *static_cast<_Tp2*>(NULL)) __result;
__result
operator()(const _Tp1& __x, const _Tp2& __y) const
{ return __x * __y; }
};
template<typename _Tp, typename _DifferenceTp> // Partial specialization for one type. Same as std::multiplies.
class _PseudoSequence; template<typename _Tp>
struct _Multiplies<_Tp, _Tp> : public std::binary_function<_Tp, _Tp, _Tp>
{
typedef __typeof__(*static_cast<_Tp*>(NULL)
* *static_cast<_Tp*>(NULL)) __result;
/** @brief _Iterator associated with __gnu_parallel::_PseudoSequence. __result
* If features the usual random-access iterator functionality. operator()(const _Tp& __x, const _Tp& __y) const
* @param _Tp Sequence _M_value type. { return __x * __y; }
* @param _DifferenceType Sequence difference type. };
*/
template<typename _Tp, typename _DifferenceTp>
class _PseudoSequenceIterator
{
public:
typedef _DifferenceTp _DifferenceType;
private:
const _Tp& _M_val;
_DifferenceType _M_pos;
public: template<typename _Tp, typename _DifferenceTp>
_PseudoSequenceIterator(const _Tp& _M_val, _DifferenceType _M_pos) class _PseudoSequence;
: _M_val(_M_val), _M_pos(_M_pos) { }
// Pre-increment operator. /** @brief _Iterator associated with __gnu_parallel::_PseudoSequence.
_PseudoSequenceIterator& * If features the usual random-access iterator functionality.
operator++() * @param _Tp Sequence _M_value type.
* @param _DifferenceType Sequence difference type.
*/
template<typename _Tp, typename _DifferenceTp>
class _PseudoSequenceIterator
{ {
++_M_pos; public:
return *this; typedef _DifferenceTp _DifferenceType;
}
// Post-increment operator. private:
const _PseudoSequenceIterator const _Tp& _M_val;
operator++(int) _DifferenceType _M_pos;
{ return _PseudoSequenceIterator(_M_pos++); }
const _Tp& public:
operator*() const _PseudoSequenceIterator(const _Tp& __val, _DifferenceType __pos)
{ return _M_val; } : _M_val(__val), _M_pos(__pos) { }
const _Tp& // Pre-increment operator.
operator[](_DifferenceType) const _PseudoSequenceIterator&
{ return _M_val; } operator++()
{
bool ++_M_pos;
operator==(const _PseudoSequenceIterator& __i2) return *this;
{ return _M_pos == __i2._M_pos; } }
_DifferenceType
operator!=(const _PseudoSequenceIterator& __i2)
{ return _M_pos != __i2._M_pos; }
_DifferenceType
operator-(const _PseudoSequenceIterator& __i2)
{ return _M_pos - __i2._M_pos; }
};
/** @brief Sequence that conceptually consists of multiple copies of
the same element.
* The copies are not stored explicitly, of course.
* @param _Tp Sequence _M_value type.
* @param _DifferenceType Sequence difference type.
*/
template<typename _Tp, typename _DifferenceTp>
class _PseudoSequence
{
public:
typedef _DifferenceTp _DifferenceType;
// Better cast down to uint64_t, than up to _DifferenceTp.
typedef _PseudoSequenceIterator<_Tp, uint64_t> iterator;
/** @brief Constructor. // Post-increment operator.
* @param _M_val Element of the sequence. const _PseudoSequenceIterator
* @param __count Number of (virtual) copies. operator++(int)
{ return _PseudoSequenceIterator(_M_pos++); }
const _Tp&
operator*() const
{ return _M_val; }
const _Tp&
operator[](_DifferenceType) const
{ return _M_val; }
bool
operator==(const _PseudoSequenceIterator& __i2)
{ return _M_pos == __i2._M_pos; }
_DifferenceType
operator!=(const _PseudoSequenceIterator& __i2)
{ return _M_pos != __i2._M_pos; }
_DifferenceType
operator-(const _PseudoSequenceIterator& __i2)
{ return _M_pos - __i2._M_pos; }
};
/** @brief Sequence that conceptually consists of multiple copies of
the same element.
* The copies are not stored explicitly, of course.
* @param _Tp Sequence _M_value type.
* @param _DifferenceType Sequence difference type.
*/ */
_PseudoSequence(const _Tp& _M_val, _DifferenceType __count) template<typename _Tp, typename _DifferenceTp>
: _M_val(_M_val), __count(__count) { } class _PseudoSequence
{
/** @brief Begin iterator. */ public:
iterator typedef _DifferenceTp _DifferenceType;
begin() const
{ return iterator(_M_val, 0); } // Better cast down to uint64_t, than up to _DifferenceTp.
typedef _PseudoSequenceIterator<_Tp, uint64_t> iterator;
/** @brief End iterator. */
iterator /** @brief Constructor.
end() const * @param _M_val Element of the sequence.
{ return iterator(_M_val, __count); } * @param __count Number of (virtual) copies.
*/
private: _PseudoSequence(const _Tp& __val, _DifferenceType __count)
const _Tp& _M_val; : _M_val(__val), _M_count(__count) { }
_DifferenceType __count;
}; /** @brief Begin iterator. */
iterator
/** @brief Functor that does nothing */ begin() const
template<typename _ValueTp> { return iterator(_M_val, 0); }
class _VoidFunctor
{ /** @brief End iterator. */
inline void iterator
operator()(const _ValueTp& __v) const { } end() const
}; { return iterator(_M_val, _M_count); }
/** @brief Compute the median of three referenced elements, private:
according to @__c __comp. const _Tp& _M_val;
* @param __a First iterator. _DifferenceType _M_count;
* @param __b Second iterator. };
* @param __c Third iterator.
* @param __comp Comparator. /** @brief Functor that does nothing */
*/ template<typename _ValueTp>
template<typename _RAIter, typename _Compare> class _VoidFunctor
_RAIter {
__median_of_three_iterators(_RAIter __a, _RAIter __b, inline void
_RAIter __c, _Compare& __comp) operator()(const _ValueTp& __v) const { }
{ };
if (__comp(*__a, *__b))
if (__comp(*__b, *__c)) /** @brief Compute the median of three referenced elements,
return __b; according to @__c __comp.
* @param __a First iterator.
* @param __b Second iterator.
* @param __c Third iterator.
* @param __comp Comparator.
*/
template<typename _RAIter, typename _Compare>
_RAIter
__median_of_three_iterators(_RAIter __a, _RAIter __b,
_RAIter __c, _Compare& __comp)
{
if (__comp(*__a, *__b))
if (__comp(*__b, *__c))
return __b;
else
if (__comp(*__a, *__c))
return __c;
else
return __a;
else else
if (__comp(*__a, *__c)) {
return __c; // Just swap __a and __b.
else if (__comp(*__a, *__c))
return __a; return __a;
else else
{ if (__comp(*__b, *__c))
// Just swap __a and __b. return __c;
if (__comp(*__a, *__c)) else
return __a; return __b;
else }
if (__comp(*__b, *__c)) }
return __c;
else
return __b;
}
}
#define _GLIBCXX_PARALLEL_ASSERT(_Condition) __glibcxx_assert(_Condition) #define _GLIBCXX_PARALLEL_ASSERT(_Condition) __glibcxx_assert(_Condition)
......
...@@ -163,7 +163,8 @@ template<typename _Tp, typename _Compare> ...@@ -163,7 +163,8 @@ template<typename _Tp, typename _Compare>
*/ */
template<bool __stable/* default == true */, typename _Tp, template<bool __stable/* default == true */, typename _Tp,
typename _Compare> typename _Compare>
class _LoserTree : public _LoserTreeBase<_Tp, _Compare> class _LoserTree
: public _LoserTreeBase<_Tp, _Compare>
{ {
typedef _LoserTreeBase<_Tp, _Compare> _Base; typedef _LoserTreeBase<_Tp, _Compare> _Base;
using _Base::_M_k; using _Base::_M_k;
...@@ -797,7 +798,7 @@ public: ...@@ -797,7 +798,7 @@ public:
* run empty. This is a very fast variant. * run empty. This is a very fast variant.
*/ */
template<typename _Tp, typename _Compare> template<typename _Tp, typename _Compare>
class LoserTreePointerUnguardedBase class _LoserTreePointerUnguardedBase
{ {
protected: protected:
struct _Loser struct _Loser
...@@ -812,8 +813,8 @@ template<typename _Tp, typename _Compare> ...@@ -812,8 +813,8 @@ template<typename _Tp, typename _Compare>
public: public:
LoserTreePointerUnguardedBase(unsigned int __k, const _Tp& _sentinel, _LoserTreePointerUnguardedBase(unsigned int __k, const _Tp& _sentinel,
_Compare __comp = std::less<_Tp>()) _Compare __comp = std::less<_Tp>())
: _M_comp(__comp) : _M_comp(__comp)
{ {
_M_ik = __k; _M_ik = __k;
...@@ -831,7 +832,7 @@ template<typename _Tp, typename _Compare> ...@@ -831,7 +832,7 @@ template<typename _Tp, typename _Compare>
} }
} }
~LoserTreePointerUnguardedBase() ~_LoserTreePointerUnguardedBase()
{ delete[] _M_losers; } { delete[] _M_losers; }
int int
...@@ -861,16 +862,16 @@ template<typename _Tp, typename _Compare> ...@@ -861,16 +862,16 @@ template<typename _Tp, typename _Compare>
*/ */
template<bool __stable/* default == true */, typename _Tp, typename _Compare> template<bool __stable/* default == true */, typename _Tp, typename _Compare>
class _LoserTreePointerUnguarded class _LoserTreePointerUnguarded
: public LoserTreePointerUnguardedBase<_Tp, _Compare> : public _LoserTreePointerUnguardedBase<_Tp, _Compare>
{ {
typedef LoserTreePointerUnguardedBase<_Tp, _Compare> _Base; typedef _LoserTreePointerUnguardedBase<_Tp, _Compare> _Base;
using _Base::_M_k; using _Base::_M_k;
using _Base::_M_losers; using _Base::_M_losers;
public: public:
_LoserTreePointerUnguarded(unsigned int __k, const _Tp& _sentinel, _LoserTreePointerUnguarded(unsigned int __k, const _Tp& _sentinel,
_Compare __comp = std::less<_Tp>()) _Compare __comp = std::less<_Tp>())
: _Base::LoserTreePointerUnguardedBase(__k, _sentinel, __comp) : _Base::_LoserTreePointerUnguardedBase(__k, _sentinel, __comp)
{ } { }
unsigned int unsigned int
...@@ -945,16 +946,16 @@ template<bool __stable/* default == true */, typename _Tp, typename _Compare> ...@@ -945,16 +946,16 @@ template<bool __stable/* default == true */, typename _Tp, typename _Compare>
*/ */
template<typename _Tp, typename _Compare> template<typename _Tp, typename _Compare>
class _LoserTreePointerUnguarded</* __stable == */false, _Tp, _Compare> class _LoserTreePointerUnguarded</* __stable == */false, _Tp, _Compare>
: public LoserTreePointerUnguardedBase<_Tp, _Compare> : public _LoserTreePointerUnguardedBase<_Tp, _Compare>
{ {
typedef LoserTreePointerUnguardedBase<_Tp, _Compare> _Base; typedef _LoserTreePointerUnguardedBase<_Tp, _Compare> _Base;
using _Base::_M_k; using _Base::_M_k;
using _Base::_M_losers; using _Base::_M_losers;
public: public:
_LoserTreePointerUnguarded(unsigned int __k, const _Tp& _sentinel, _LoserTreePointerUnguarded(unsigned int __k, const _Tp& _sentinel,
_Compare __comp = std::less<_Tp>()) _Compare __comp = std::less<_Tp>())
: _Base::LoserTreePointerUnguardedBase(__k, _sentinel, __comp) : _Base::_LoserTreePointerUnguardedBase(__k, _sentinel, __comp)
{ } { }
unsigned int unsigned int
......
...@@ -54,24 +54,6 @@ ...@@ -54,24 +54,6 @@
namespace __gnu_parallel namespace __gnu_parallel
{ {
// Announce guarded and unguarded iterator.
template<typename _RAIter, typename _Compare>
class _GuardedIterator;
// Making the arguments const references seems to dangerous,
// the user-defined comparator might not be const.
template<typename _RAIter, typename _Compare>
inline bool
operator<(_GuardedIterator<_RAIter, _Compare>& __bi1,
_GuardedIterator<_RAIter, _Compare>& __bi2);
template<typename _RAIter, typename _Compare>
inline bool
operator<=(_GuardedIterator<_RAIter, _Compare>& __bi1,
_GuardedIterator<_RAIter, _Compare>& __bi2);
/** @brief _Iterator wrapper supporting an implicit supremum at the end /** @brief _Iterator wrapper supporting an implicit supremum at the end
* of the sequence, dominating all comparisons. * of the sequence, dominating all comparisons.
* *
...@@ -96,12 +78,11 @@ template<typename _RAIter, typename _Compare> ...@@ -96,12 +78,11 @@ template<typename _RAIter, typename _Compare>
public: public:
/** @brief Constructor. Sets iterator to beginning of sequence. /** @brief Constructor. Sets iterator to beginning of sequence.
* @param __begin Begin iterator of sequence. * @param __begin Begin iterator of sequence.
* @param _M_end End iterator of sequence. * @param __end End iterator of sequence.
* @param __comp Comparator provided for associated overloaded * @param __comp Comparator provided for associated overloaded
* compare operators. */ * compare operators. */
_GuardedIterator(_RAIter __begin, _GuardedIterator(_RAIter __begin, _RAIter __end, _Compare& __comp)
_RAIter _M_end, _Compare& __comp) : _M_current(__begin), _M_end(__end), __comp(__comp)
: _M_current(__begin), _M_end(_M_end), __comp(__comp)
{ } { }
/** @brief Pre-increment operator. /** @brief Pre-increment operator.
...@@ -124,62 +105,37 @@ template<typename _RAIter, typename _Compare> ...@@ -124,62 +105,37 @@ template<typename _RAIter, typename _Compare>
operator _RAIter() operator _RAIter()
{ return _M_current; } { return _M_current; }
/** @brief Compare two elements referenced by guarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c true if less. */
friend bool friend bool
operator< <_RAIter, _Compare>( operator<(_GuardedIterator<_RAIter, _Compare>& __bi1,
_GuardedIterator<_RAIter, _Compare>& __bi1, _GuardedIterator<_RAIter, _Compare>& __bi2)
_GuardedIterator<_RAIter, _Compare>& __bi2); {
if (__bi1._M_current == __bi1._M_end) //__bi1 is sup
return __bi2._M_current == __bi2._M_end; //__bi2 is not sup
if (__bi2._M_current == __bi2._M_end) //__bi2 is sup
return true;
return (__bi1.__comp)(*__bi1, *__bi2); //normal compare
}
/** @brief Compare two elements referenced by guarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c True if less equal. */
friend bool friend bool
operator<= <_RAIter, _Compare>( operator<=(_GuardedIterator<_RAIter, _Compare>& __bi1,
_GuardedIterator<_RAIter, _Compare>& __bi1, _GuardedIterator<_RAIter, _Compare>& __bi2)
_GuardedIterator<_RAIter, _Compare>& __bi2); {
if (__bi2._M_current == __bi2._M_end) //__bi1 is sup
return __bi1._M_current != __bi1._M_end; //__bi2 is not sup
if (__bi1._M_current == __bi1._M_end) //__bi2 is sup
return false;
return !(__bi1.__comp)(*__bi2, *__bi1); //normal compare
}
}; };
/** @brief Compare two elements referenced by guarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c true if less. */
template<typename _RAIter, typename _Compare>
inline bool
operator<(_GuardedIterator<_RAIter, _Compare>& __bi1,
_GuardedIterator<_RAIter, _Compare>& __bi2)
{
if (__bi1._M_current == __bi1._M_end) //__bi1 is sup
return __bi2._M_current == __bi2._M_end; //__bi2 is not sup
if (__bi2._M_current == __bi2._M_end) //__bi2 is sup
return true;
return (__bi1.__comp)(*__bi1, *__bi2); //normal compare
}
/** @brief Compare two elements referenced by guarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c True if less equal. */
template<typename _RAIter, typename _Compare>
inline bool
operator<=(_GuardedIterator<_RAIter, _Compare>& __bi1,
_GuardedIterator<_RAIter, _Compare>& __bi2)
{
if (__bi2._M_current == __bi2._M_end) //__bi1 is sup
return __bi1._M_current != __bi1._M_end; //__bi2 is not sup
if (__bi1._M_current == __bi1._M_end) //__bi2 is sup
return false;
return !(__bi1.__comp)(*__bi2, *__bi1); //normal compare
}
template<typename _RAIter, typename _Compare>
class _UnguardedIterator;
template<typename _RAIter, typename _Compare>
inline bool
operator<(_UnguardedIterator<_RAIter, _Compare>& __bi1,
_UnguardedIterator<_RAIter, _Compare>& __bi2);
template<typename _RAIter, typename _Compare>
inline bool
operator<=(_UnguardedIterator<_RAIter, _Compare>& __bi1,
_UnguardedIterator<_RAIter, _Compare>& __bi2);
template<typename _RAIter, typename _Compare> template<typename _RAIter, typename _Compare>
class _UnguardedIterator class _UnguardedIterator
{ {
...@@ -192,10 +148,10 @@ template<typename _RAIter, typename _Compare> ...@@ -192,10 +148,10 @@ template<typename _RAIter, typename _Compare>
public: public:
/** @brief Constructor. Sets iterator to beginning of sequence. /** @brief Constructor. Sets iterator to beginning of sequence.
* @param __begin Begin iterator of sequence. * @param __begin Begin iterator of sequence.
* @param _M_end Unused, only for compatibility. * @param __end Unused, only for compatibility.
* @param __comp Unused, only for compatibility. */ * @param __comp Unused, only for compatibility. */
_UnguardedIterator(_RAIter __begin, _UnguardedIterator(_RAIter __begin,
_RAIter _M_end, _Compare& __comp) _RAIter /* __end */, _Compare& __comp)
: _M_current(__begin), __comp(__comp) : _M_current(__begin), __comp(__comp)
{ } { }
...@@ -219,43 +175,31 @@ template<typename _RAIter, typename _Compare> ...@@ -219,43 +175,31 @@ template<typename _RAIter, typename _Compare>
operator _RAIter() operator _RAIter()
{ return _M_current; } { return _M_current; }
/** @brief Compare two elements referenced by unguarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c true if less. */
friend bool friend bool
operator< <_RAIter, _Compare>( operator<(_UnguardedIterator<_RAIter, _Compare>& __bi1,
_UnguardedIterator<_RAIter, _Compare>& __bi1, _UnguardedIterator<_RAIter, _Compare>& __bi2)
_UnguardedIterator<_RAIter, _Compare>& __bi2); {
// Normal compare.
return (__bi1.__comp)(*__bi1, *__bi2);
}
/** @brief Compare two elements referenced by unguarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c True if less equal. */
friend bool friend bool
operator<= <_RAIter, _Compare>( operator<=(_UnguardedIterator<_RAIter, _Compare>& __bi1,
_UnguardedIterator<_RAIter, _Compare>& __bi1, _UnguardedIterator<_RAIter, _Compare>& __bi2)
_UnguardedIterator<_RAIter, _Compare>& __bi2); {
// Normal compare.
return !(__bi1.__comp)(*__bi2, *__bi1);
}
}; };
/** @brief Compare two elements referenced by unguarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c true if less. */
template<typename _RAIter, typename _Compare>
inline bool
operator<(_UnguardedIterator<_RAIter, _Compare>& __bi1,
_UnguardedIterator<_RAIter, _Compare>& __bi2)
{
// Normal compare.
return (__bi1.__comp)(*__bi1, *__bi2);
}
/** @brief Compare two elements referenced by unguarded iterators.
* @param __bi1 First iterator.
* @param __bi2 Second iterator.
* @return @__c True if less equal. */
template<typename _RAIter, typename _Compare>
inline bool
operator<=(_UnguardedIterator<_RAIter, _Compare>& __bi1,
_UnguardedIterator<_RAIter, _Compare>& __bi2)
{
// Normal compare.
return !(__bi1.__comp)(*__bi2, *__bi1);
}
/** @brief Highly efficient 3-way merging procedure. /** @brief Highly efficient 3-way merging procedure.
* *
* Merging is done with the algorithm implementation described by Peter * Merging is done with the algorithm implementation described by Peter
...@@ -287,11 +231,10 @@ template<template<typename RAI, typename C> class iterator, ...@@ -287,11 +231,10 @@ template<template<typename RAI, typename C> class iterator,
typename _DifferenceTp, typename _DifferenceTp,
typename _Compare> typename _Compare>
_RAIter3 _RAIter3
multiway_merge_3_variant( multiway_merge_3_variant(_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,
_RAIterIterator __seqs_end, _RAIter3 __target,
_RAIter3 __target, _DifferenceTp __length, _Compare __comp)
_DifferenceTp __length, _Compare __comp)
{ {
_GLIBCXX_CALL(__length); _GLIBCXX_CALL(__length);
...@@ -612,15 +555,14 @@ template<typename _LT, ...@@ -612,15 +555,14 @@ template<typename _LT,
typename _RAIter3, typename _RAIter3,
typename _DifferenceTp, typename _Compare> typename _DifferenceTp, typename _Compare>
_RAIter3 _RAIter3
multiway_merge_loser_tree_unguarded( multiway_merge_loser_tree_unguarded(_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,
_RAIterIterator __seqs_end, _RAIter3 __target,
_RAIter3 __target, const typename std::iterator_traits<typename std::iterator_traits<
const typename std::iterator_traits<typename std::iterator_traits< _RAIterIterator>::value_type::first_type>::value_type&
_RAIterIterator>::value_type::first_type>::value_type& __sentinel,
__sentinel, _DifferenceTp __length,
_DifferenceTp __length, _Compare __comp)
_Compare __comp)
{ {
_GLIBCXX_CALL(__length) _GLIBCXX_CALL(__length)
typedef _DifferenceTp _DifferenceType; typedef _DifferenceTp _DifferenceType;
...@@ -702,15 +644,14 @@ template<typename UnguardedLoserTree, ...@@ -702,15 +644,14 @@ template<typename UnguardedLoserTree,
typename _DifferenceTp, typename _DifferenceTp,
typename _Compare> typename _Compare>
_RAIter3 _RAIter3
multiway_merge_loser_tree_sentinel( multiway_merge_loser_tree_sentinel(_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,
_RAIterIterator __seqs_end, _RAIter3 __target,
_RAIter3 __target,
const typename std::iterator_traits<typename std::iterator_traits< const typename std::iterator_traits<typename std::iterator_traits<
_RAIterIterator>::value_type::first_type>::value_type& _RAIterIterator>::value_type::first_type>::value_type&
__sentinel, __sentinel,
_DifferenceTp __length, _DifferenceTp __length,
_Compare __comp) _Compare __comp)
{ {
_GLIBCXX_CALL(__length) _GLIBCXX_CALL(__length)
...@@ -773,16 +714,16 @@ template<typename UnguardedLoserTree, ...@@ -773,16 +714,16 @@ template<typename UnguardedLoserTree,
* @param _Tp type to give the loser tree traits for. * @param _Tp type to give the loser tree traits for.
*/ */
template <typename _Tp> template <typename _Tp>
struct _LoserTreeTraits struct _LoserTreeTraits
{ {
/** /**
* @brief True iff to use pointers instead of values in loser trees. * @brief True iff to use pointers instead of values in loser trees.
* *
* The default behavior is to use pointers if the data type is four * The default behavior is to use pointers if the data type is four
* times as big as the pointer to it. * times as big as the pointer to it.
*/ */
static const bool _M_use_pointer = (sizeof(_Tp) > 4 * sizeof(_Tp*)); static const bool _M_use_pointer = (sizeof(_Tp) > 4 * sizeof(_Tp*));
}; };
/** /**
* @brief Switch for 3-way merging with __sentinels turned off. * @brief Switch for 3-way merging with __sentinels turned off.
...@@ -796,10 +737,11 @@ template<bool __sentinels /*default == false*/, ...@@ -796,10 +737,11 @@ template<bool __sentinels /*default == false*/,
typename _Compare> typename _Compare>
struct __multiway_merge_3_variant_sentinel_switch struct __multiway_merge_3_variant_sentinel_switch
{ {
_RAIter3 operator()(_RAIterIterator __seqs_begin, _RAIter3
_RAIterIterator __seqs_end, operator()(_RAIterIterator __seqs_begin,
_RAIter3 __target, _RAIterIterator __seqs_end,
_DifferenceTp __length, _Compare __comp) _RAIter3 __target,
_DifferenceTp __length, _Compare __comp)
{ {
return multiway_merge_3_variant<_GuardedIterator> return multiway_merge_3_variant<_GuardedIterator>
(__seqs_begin, __seqs_end, __target, __length, __comp); (__seqs_begin, __seqs_end, __target, __length, __comp);
...@@ -815,13 +757,15 @@ template<typename _RAIterIterator, ...@@ -815,13 +757,15 @@ template<typename _RAIterIterator,
typename _RAIter3, typename _RAIter3,
typename _DifferenceTp, typename _DifferenceTp,
typename _Compare> typename _Compare>
struct __multiway_merge_3_variant_sentinel_switch struct __multiway_merge_3_variant_sentinel_switch<true, _RAIterIterator,
<true, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare> _RAIter3, _DifferenceTp,
_Compare>
{ {
_RAIter3 operator()(_RAIterIterator __seqs_begin, _RAIter3
_RAIterIterator __seqs_end, operator()(_RAIterIterator __seqs_begin,
_RAIter3 __target, _RAIterIterator __seqs_end,
_DifferenceTp __length, _Compare __comp) _RAIter3 __target,
_DifferenceTp __length, _Compare __comp)
{ {
return multiway_merge_3_variant<_UnguardedIterator> return multiway_merge_3_variant<_UnguardedIterator>
(__seqs_begin, __seqs_end, __target, __length, __comp); (__seqs_begin, __seqs_end, __target, __length, __comp);
...@@ -840,10 +784,11 @@ template<bool __sentinels /*default == false*/, ...@@ -840,10 +784,11 @@ template<bool __sentinels /*default == false*/,
typename _Compare> typename _Compare>
struct __multiway_merge_4_variant_sentinel_switch struct __multiway_merge_4_variant_sentinel_switch
{ {
_RAIter3 operator()(_RAIterIterator __seqs_begin, _RAIter3
_RAIterIterator __seqs_end, operator()(_RAIterIterator __seqs_begin,
_RAIter3 __target, _RAIterIterator __seqs_end,
_DifferenceTp __length, _Compare __comp) _RAIter3 __target,
_DifferenceTp __length, _Compare __comp)
{ {
return multiway_merge_4_variant<_GuardedIterator> return multiway_merge_4_variant<_GuardedIterator>
(__seqs_begin, __seqs_end, __target, __length, __comp); (__seqs_begin, __seqs_end, __target, __length, __comp);
...@@ -859,13 +804,15 @@ template<typename _RAIterIterator, ...@@ -859,13 +804,15 @@ template<typename _RAIterIterator,
typename _RAIter3, typename _RAIter3,
typename _DifferenceTp, typename _DifferenceTp,
typename _Compare> typename _Compare>
struct __multiway_merge_4_variant_sentinel_switch struct __multiway_merge_4_variant_sentinel_switch<true, _RAIterIterator,
<true, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare> _RAIter3, _DifferenceTp,
_Compare>
{ {
_RAIter3 operator()(_RAIterIterator __seqs_begin, _RAIter3
_RAIterIterator __seqs_end, operator()(_RAIterIterator __seqs_begin,
_RAIter3 __target, _RAIterIterator __seqs_end,
_DifferenceTp __length, _Compare __comp) _RAIter3 __target,
_DifferenceTp __length, _Compare __comp)
{ {
return multiway_merge_4_variant<_UnguardedIterator> return multiway_merge_4_variant<_UnguardedIterator>
(__seqs_begin, __seqs_end, __target, __length, __comp); (__seqs_begin, __seqs_end, __target, __length, __comp);
...@@ -882,30 +829,30 @@ template<bool __sentinels, ...@@ -882,30 +829,30 @@ template<bool __sentinels,
typename _DifferenceTp, typename _DifferenceTp,
typename _Compare> typename _Compare>
struct __multiway_merge_k_variant_sentinel_switch struct __multiway_merge_k_variant_sentinel_switch
{ {
_RAIter3 operator() _RAIter3
(_RAIterIterator __seqs_begin, operator()(_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_end, _RAIterIterator __seqs_end,
_RAIter3 __target, _RAIter3 __target,
const typename std::iterator_traits<typename std::iterator_traits< const typename std::iterator_traits<typename std::iterator_traits<
_RAIterIterator>::value_type::first_type>::value_type& _RAIterIterator>::value_type::first_type>::value_type&
__sentinel, __sentinel,
_DifferenceTp __length, _Compare __comp) _DifferenceTp __length, _Compare __comp)
{ {
typedef typename std::iterator_traits<_RAIterIterator> typedef typename std::iterator_traits<_RAIterIterator>
::value_type::first_type ::value_type::first_type
_RAIter1; _RAIter1;
typedef typename std::iterator_traits<_RAIter1>::value_type typedef typename std::iterator_traits<_RAIter1>::value_type
_ValueType; _ValueType;
return multiway_merge_loser_tree_sentinel< return multiway_merge_loser_tree_sentinel<
typename __gnu_cxx::__conditional_type< typename __gnu_cxx::__conditional_type<
_LoserTreeTraits<_ValueType>::_M_use_pointer, _LoserTreeTraits<_ValueType>::_M_use_pointer,
_LoserTreePointerUnguarded<__stable, _ValueType, _Compare>, _LoserTreePointerUnguarded<__stable, _ValueType, _Compare>,
_LoserTreeUnguarded<__stable, _ValueType, _Compare> _LoserTreeUnguarded<__stable, _ValueType, _Compare>
>::__type>( >::__type>
__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp);
} }
}; };
/** /**
...@@ -916,17 +863,18 @@ template<bool __stable, ...@@ -916,17 +863,18 @@ template<bool __stable,
typename _RAIter3, typename _RAIter3,
typename _DifferenceTp, typename _DifferenceTp,
typename _Compare> typename _Compare>
struct __multiway_merge_k_variant_sentinel_switch struct __multiway_merge_k_variant_sentinel_switch<false, __stable,
<false, __stable, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare> _RAIterIterator, _RAIter3,
_DifferenceTp, _Compare>
{ {
_RAIter3 operator() _RAIter3
(_RAIterIterator __seqs_begin, operator()(_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_end, _RAIterIterator __seqs_end,
_RAIter3 __target, _RAIter3 __target,
const typename std::iterator_traits<typename std::iterator_traits< const typename std::iterator_traits<typename std::iterator_traits<
_RAIterIterator>::value_type::first_type>::value_type& _RAIterIterator>::value_type::first_type>::value_type&
__sentinel, __sentinel,
_DifferenceTp __length, _Compare __comp) _DifferenceTp __length, _Compare __comp)
{ {
typedef typename std::iterator_traits<_RAIterIterator> typedef typename std::iterator_traits<_RAIterIterator>
::value_type::first_type ::value_type::first_type
...@@ -963,14 +911,13 @@ template<bool __stable, ...@@ -963,14 +911,13 @@ template<bool __stable,
typename _DifferenceTp, typename _DifferenceTp,
typename _Compare> typename _Compare>
_RAIter3 _RAIter3
__sequential_multiway_merge( __sequential_multiway_merge(_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,
_RAIterIterator __seqs_end, _RAIter3 __target,
_RAIter3 __target,
const typename std::iterator_traits<typename std::iterator_traits< const typename std::iterator_traits<typename std::iterator_traits<
_RAIterIterator>::value_type::first_type>::value_type& _RAIterIterator>::value_type::first_type>::value_type&
__sentinel, __sentinel,
_DifferenceTp __length, _Compare __comp) _DifferenceTp __length, _Compare __comp)
{ {
_GLIBCXX_CALL(__length) _GLIBCXX_CALL(__length)
...@@ -1061,8 +1008,8 @@ template<bool __stable, ...@@ -1061,8 +1008,8 @@ template<bool __stable,
template<bool __stable, class _RAIter, class _StrictWeakOrdering> template<bool __stable, class _RAIter, class _StrictWeakOrdering>
struct _SamplingSorter struct _SamplingSorter
{ {
void operator()(_RAIter __first, _RAIter __last, void
_StrictWeakOrdering __comp) operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp)
{ __gnu_sequential::stable_sort(__first, __last, __comp); } { __gnu_sequential::stable_sort(__first, __last, __comp); }
}; };
...@@ -1074,8 +1021,8 @@ template<bool __stable, class _RAIter, class _StrictWeakOrdering> ...@@ -1074,8 +1021,8 @@ template<bool __stable, class _RAIter, class _StrictWeakOrdering>
template<class _RAIter, class _StrictWeakOrdering> template<class _RAIter, class _StrictWeakOrdering>
struct _SamplingSorter<false, _RAIter, _StrictWeakOrdering> struct _SamplingSorter<false, _RAIter, _StrictWeakOrdering>
{ {
void operator()(_RAIter __first, _RAIter __last, void
_StrictWeakOrdering __comp) operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp)
{ __gnu_sequential::sort(__first, __last, __comp); } { __gnu_sequential::sort(__first, __last, __comp); }
}; };
...@@ -1087,10 +1034,11 @@ template<bool __stable, ...@@ -1087,10 +1034,11 @@ template<bool __stable,
typename _Compare, typename _Compare,
typename _DifferenceType> typename _DifferenceType>
void void
multiway_merge_sampling_splitting multiway_merge_sampling_splitting(_RAIterIterator __seqs_begin,
(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,
_RAIterIterator __seqs_end, _DifferenceType __length,
_DifferenceType __length, _DifferenceType __total_length, _Compare __comp, _DifferenceType __total_length,
_Compare __comp,
std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces)
{ {
typedef typename std::iterator_traits<_RAIterIterator> typedef typename std::iterator_traits<_RAIterIterator>
...@@ -1168,11 +1116,11 @@ template<bool __stable, ...@@ -1168,11 +1116,11 @@ template<bool __stable,
typename _Compare, typename _Compare,
typename _DifferenceType> typename _DifferenceType>
void void
multiway_merge_exact_splitting multiway_merge_exact_splitting(_RAIterIterator __seqs_begin,
(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,
_RAIterIterator __seqs_end, _DifferenceType __length,
_DifferenceType __length, _DifferenceType __total_length, _DifferenceType __total_length,
_Compare __comp, _Compare __comp,
std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces)
{ {
typedef typename std::iterator_traits<_RAIterIterator> typedef typename std::iterator_traits<_RAIterIterator>
......
...@@ -41,451 +41,444 @@ ...@@ -41,451 +41,444 @@
namespace __gnu_parallel namespace __gnu_parallel
{ {
/** @brief Subsequence description. */
template<typename _DifferenceTp>
struct _Piece
{
typedef _DifferenceTp _DifferenceType;
/** @brief Subsequence description. */ /** @brief Begin of subsequence. */
template<typename _DifferenceTp> _DifferenceType _M_begin;
struct _Piece
{
typedef _DifferenceTp _DifferenceType;
/** @brief Begin of subsequence. */ /** @brief End of subsequence. */
_DifferenceType _M_begin; _DifferenceType _M_end;
};
/** @brief End of subsequence. */ /** @brief Data accessed by all threads.
_DifferenceType _M_end; *
}; * PMWMS = parallel multiway mergesort */
template<typename _RAIter>
struct _PMWMSSortingData
{
typedef std::iterator_traits<_RAIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType;
/** @brief Data accessed by all threads. /** @brief Number of threads involved. */
* _ThreadIndex _M_num_threads;
* PMWMS = parallel multiway mergesort */
template<typename _RAIter>
struct _PMWMSSortingData
{
typedef std::iterator_traits<_RAIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType;
/** @brief Number of threads involved. */
_ThreadIndex _M_num_threads;
/** @brief Input __begin. */
_RAIter _M_source;
/** @brief Start indices, per thread. */
_DifferenceType* _M_starts;
/** @brief Storage in which to sort. */
_ValueType** _M_temporary;
/** @brief Samples. */
_ValueType* _M_samples;
/** @brief Offsets to add to the found positions. */
_DifferenceType* _M_offsets;
/** @brief Pieces of data to merge @__c [thread][__sequence] */
std::vector<_Piece<_DifferenceType> >* _M_pieces;
};
/**
* @brief Select _M_samples from a sequence.
* @param __sd Pointer to algorithm data. _Result will be placed in
* @__c __sd->_M_samples.
* @param __num_samples Number of _M_samples to select.
*/
template<typename _RAIter, typename _DifferenceTp>
void
__determine_samples(_PMWMSSortingData<_RAIter>* __sd,
_DifferenceTp __num_samples)
{
typedef std::iterator_traits<_RAIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType;
typedef _DifferenceTp _DifferenceType;
_ThreadIndex __iam = omp_get_thread_num();
_DifferenceType* __es = new _DifferenceType[__num_samples + 2];
equally_split(__sd->_M_starts[__iam + 1] - __sd->_M_starts[__iam],
__num_samples + 1, __es);
for (_DifferenceType __i = 0; __i < __num_samples; ++__i)
::new(&(__sd->_M_samples[__iam * __num_samples + __i]))
_ValueType(__sd->_M_source[__sd->_M_starts[__iam] + __es[__i + 1]]);
delete[] __es;
}
/** @brief Split consistently. */
template<bool __exact, typename _RAIter,
typename _Compare, typename _SortingPlacesIterator>
struct _SplitConsistently
{
};
/** @brief Split by exact splitting. */ /** @brief Input __begin. */
template<typename _RAIter, typename _Compare, _RAIter _M_source;
typename _SortingPlacesIterator>
struct _SplitConsistently
<true, _RAIter, _Compare, _SortingPlacesIterator>
{
void operator()(
const _ThreadIndex __iam,
_PMWMSSortingData<_RAIter>* __sd,
_Compare& __comp,
const typename
std::iterator_traits<_RAIter>::difference_type
__num_samples)
const
{
# pragma omp barrier
std::vector<std::pair<_SortingPlacesIterator, _SortingPlacesIterator> >
seqs(__sd->_M_num_threads);
for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; __s++)
seqs[__s] = std::make_pair(__sd->_M_temporary[__s],
__sd->_M_temporary[__s]
+ (__sd->_M_starts[__s + 1]
- __sd->_M_starts[__s]));
std::vector<_SortingPlacesIterator> _M_offsets(__sd->_M_num_threads);
// if not last thread
if (__iam < __sd->_M_num_threads - 1)
multiseq_partition(seqs.begin(), seqs.end(),
__sd->_M_starts[__iam + 1], _M_offsets.begin(),
__comp);
for (int __seq = 0; __seq < __sd->_M_num_threads; __seq++)
{
// for each sequence
if (__iam < (__sd->_M_num_threads - 1))
__sd->_M_pieces[__iam][__seq]._M_end
= _M_offsets[__seq] - seqs[__seq].first;
else
// very end of this sequence
__sd->_M_pieces[__iam][__seq]._M_end =
__sd->_M_starts[__seq + 1] - __sd->_M_starts[__seq];
}
# pragma omp barrier /** @brief Start indices, per thread. */
_DifferenceType* _M_starts;
for (_ThreadIndex __seq = 0; __seq < __sd->_M_num_threads; __seq++) /** @brief Storage in which to sort. */
{ _ValueType** _M_temporary;
// For each sequence.
if (__iam > 0) /** @brief Samples. */
__sd->_M_pieces[__iam][__seq]._M_begin = _ValueType* _M_samples;
__sd->_M_pieces[__iam - 1][__seq]._M_end;
else /** @brief Offsets to add to the found positions. */
// Absolute beginning. _DifferenceType* _M_offsets;
__sd->_M_pieces[__iam][__seq]._M_begin = 0;
} /** @brief Pieces of data to merge @__c [thread][__sequence] */
} std::vector<_Piece<_DifferenceType> >* _M_pieces;
}; };
/** @brief Split by sampling. */ /**
template<typename _RAIter, typename _Compare, * @brief Select _M_samples from a sequence.
typename _SortingPlacesIterator> * @param __sd Pointer to algorithm data. _Result will be placed in
struct _SplitConsistently<false, _RAIter, _Compare, * @__c __sd->_M_samples.
_SortingPlacesIterator> * @param __num_samples Number of _M_samples to select.
{ */
void operator()( template<typename _RAIter, typename _DifferenceTp>
const _ThreadIndex __iam, void
_PMWMSSortingData<_RAIter>* __sd, __determine_samples(_PMWMSSortingData<_RAIter>* __sd,
_Compare& __comp, _DifferenceTp __num_samples)
const typename
std::iterator_traits<_RAIter>::difference_type
__num_samples)
const
{ {
typedef std::iterator_traits<_RAIter> _TraitsType; typedef std::iterator_traits<_RAIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType; typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType; typedef _DifferenceTp _DifferenceType;
__determine_samples(__sd, __num_samples); _ThreadIndex __iam = omp_get_thread_num();
# pragma omp barrier _DifferenceType* __es = new _DifferenceType[__num_samples + 2];
# pragma omp single equally_split(__sd->_M_starts[__iam + 1] - __sd->_M_starts[__iam],
__gnu_sequential::sort(__sd->_M_samples, __num_samples + 1, __es);
__sd->_M_samples
+ (__num_samples * __sd->_M_num_threads),
__comp);
# pragma omp barrier for (_DifferenceType __i = 0; __i < __num_samples; ++__i)
::new(&(__sd->_M_samples[__iam * __num_samples + __i]))
_ValueType(__sd->_M_source[__sd->_M_starts[__iam]
+ __es[__i + 1]]);
delete[] __es;
}
for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; ++__s) /** @brief Split consistently. */
{ template<bool __exact, typename _RAIter,
// For each sequence. typename _Compare, typename _SortingPlacesIterator>
if (__num_samples * __iam > 0) struct _SplitConsistently
__sd->_M_pieces[__iam][__s]._M_begin = { };
/** @brief Split by exact splitting. */
template<typename _RAIter, typename _Compare,
typename _SortingPlacesIterator>
struct _SplitConsistently<true, _RAIter,
_Compare, _SortingPlacesIterator>
{
void
operator()(const _ThreadIndex __iam,
_PMWMSSortingData<_RAIter>* __sd,
_Compare& __comp,
const typename
std::iterator_traits<_RAIter>::difference_type
__num_samples) const
{
# pragma omp barrier
std::vector<std::pair<_SortingPlacesIterator,
_SortingPlacesIterator> >
seqs(__sd->_M_num_threads);
for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; __s++)
seqs[__s] = std::make_pair(__sd->_M_temporary[__s],
__sd->_M_temporary[__s]
+ (__sd->_M_starts[__s + 1]
- __sd->_M_starts[__s]));
std::vector<_SortingPlacesIterator> _M_offsets(__sd->_M_num_threads);
// if not last thread
if (__iam < __sd->_M_num_threads - 1)
multiseq_partition(seqs.begin(), seqs.end(),
__sd->_M_starts[__iam + 1], _M_offsets.begin(),
__comp);
for (int __seq = 0; __seq < __sd->_M_num_threads; __seq++)
{
// for each sequence
if (__iam < (__sd->_M_num_threads - 1))
__sd->_M_pieces[__iam][__seq]._M_end
= _M_offsets[__seq] - seqs[__seq].first;
else
// very end of this sequence
__sd->_M_pieces[__iam][__seq]._M_end =
__sd->_M_starts[__seq + 1] - __sd->_M_starts[__seq];
}
# pragma omp barrier
for (_ThreadIndex __seq = 0; __seq < __sd->_M_num_threads; __seq++)
{
// For each sequence.
if (__iam > 0)
__sd->_M_pieces[__iam][__seq]._M_begin =
__sd->_M_pieces[__iam - 1][__seq]._M_end;
else
// Absolute beginning.
__sd->_M_pieces[__iam][__seq]._M_begin = 0;
}
}
};
/** @brief Split by sampling. */
template<typename _RAIter, typename _Compare,
typename _SortingPlacesIterator>
struct _SplitConsistently<false, _RAIter, _Compare,
_SortingPlacesIterator>
{
void
operator()(const _ThreadIndex __iam,
_PMWMSSortingData<_RAIter>* __sd,
_Compare& __comp,
const typename
std::iterator_traits<_RAIter>::difference_type
__num_samples) const
{
typedef std::iterator_traits<_RAIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType;
__determine_samples(__sd, __num_samples);
# pragma omp barrier
# pragma omp single
__gnu_sequential::sort(__sd->_M_samples,
__sd->_M_samples
+ (__num_samples * __sd->_M_num_threads),
__comp);
# pragma omp barrier
for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; ++__s)
{
// For each sequence.
if (__num_samples * __iam > 0)
__sd->_M_pieces[__iam][__s]._M_begin =
std::lower_bound(__sd->_M_temporary[__s], std::lower_bound(__sd->_M_temporary[__s],
__sd->_M_temporary[__s] __sd->_M_temporary[__s]
+ (__sd->_M_starts[__s + 1] - __sd->_M_starts[__s]), + (__sd->_M_starts[__s + 1]
__sd->_M_samples[__num_samples * __iam], - __sd->_M_starts[__s]),
__comp) __sd->_M_samples[__num_samples * __iam],
__comp)
- __sd->_M_temporary[__s]; - __sd->_M_temporary[__s];
else else
// Absolute beginning. // Absolute beginning.
__sd->_M_pieces[__iam][__s]._M_begin = 0; __sd->_M_pieces[__iam][__s]._M_begin = 0;
if ((__num_samples * (__iam + 1)) < if ((__num_samples * (__iam + 1)) <
(__num_samples * __sd->_M_num_threads)) (__num_samples * __sd->_M_num_threads))
__sd->_M_pieces[__iam][__s]._M_end = __sd->_M_pieces[__iam][__s]._M_end =
std::lower_bound(__sd->_M_temporary[__s], std::lower_bound(__sd->_M_temporary[__s],
__sd->_M_temporary[__s] __sd->_M_temporary[__s]
+ (__sd->_M_starts[__s + 1] - __sd->_M_starts[__s]), + (__sd->_M_starts[__s + 1]
__sd->_M_samples[__num_samples * (__iam + 1)], - __sd->_M_starts[__s]),
__comp) __sd->_M_samples[__num_samples * (__iam + 1)],
__comp)
- __sd->_M_temporary[__s]; - __sd->_M_temporary[__s];
else else
// Absolute end. // Absolute end.
__sd->_M_pieces[__iam][__s]._M_end = __sd->_M_starts[__s + 1] __sd->_M_pieces[__iam][__s]._M_end = (__sd->_M_starts[__s + 1]
- __sd->_M_starts[__s]; - __sd->_M_starts[__s]);
} }
} }
}; };
template<bool __stable, typename _RAIter, typename _Compare> template<bool __stable, typename _RAIter, typename _Compare>
struct __possibly_stable_sort struct __possibly_stable_sort
{ { };
};
template<typename _RAIter, typename _Compare> template<typename _RAIter, typename _Compare>
struct __possibly_stable_sort<true, _RAIter, _Compare> struct __possibly_stable_sort<true, _RAIter, _Compare>
{
void operator()(const _RAIter& __begin,
const _RAIter& __end, _Compare& __comp) const
{ {
__gnu_sequential::stable_sort(__begin, __end, __comp); void operator()(const _RAIter& __begin,
} const _RAIter& __end, _Compare& __comp) const
}; { __gnu_sequential::stable_sort(__begin, __end, __comp); }
};
template<typename _RAIter, typename _Compare> template<typename _RAIter, typename _Compare>
struct __possibly_stable_sort<false, _RAIter, _Compare> struct __possibly_stable_sort<false, _RAIter, _Compare>
{
void operator()(const _RAIter __begin,
const _RAIter __end, _Compare& __comp) const
{ {
__gnu_sequential::sort(__begin, __end, __comp); void operator()(const _RAIter __begin,
} const _RAIter __end, _Compare& __comp) const
}; { __gnu_sequential::sort(__begin, __end, __comp); }
};
template<bool __stable, typename Seq_RAIter,
typename _RAIter, typename _Compare, template<bool __stable, typename Seq_RAIter,
typename DiffType> typename _RAIter, typename _Compare,
struct __possibly_stable_multiway_merge typename DiffType>
{ struct __possibly_stable_multiway_merge
}; { };
template<typename Seq_RAIter, typename _RAIter, template<typename Seq_RAIter, typename _RAIter,
typename _Compare, typename DiffType> typename _Compare, typename _DiffType>
struct __possibly_stable_multiway_merge struct __possibly_stable_multiway_merge<true, Seq_RAIter,
<true, Seq_RAIter, _RAIter, _Compare, _RAIter, _Compare, _DiffType>
DiffType>
{
void operator()(const Seq_RAIter& __seqs_begin,
const Seq_RAIter& __seqs_end,
const _RAIter& __target,
_Compare& __comp,
DiffType __length_am) const
{ {
stable_multiway_merge(__seqs_begin, __seqs_end, __target, __length_am, void operator()(const Seq_RAIter& __seqs_begin,
__comp, sequential_tag()); const Seq_RAIter& __seqs_end,
} const _RAIter& __target,
}; _Compare& __comp,
_DiffType __length_am) const
{
stable_multiway_merge(__seqs_begin, __seqs_end, __target, __length_am,
__comp, sequential_tag());
}
};
template<typename Seq_RAIter, typename _RAIter, template<typename Seq_RAIter, typename _RAIter,
typename _Compare, typename DiffType> typename _Compare, typename _DiffType>
struct __possibly_stable_multiway_merge struct __possibly_stable_multiway_merge<false, Seq_RAIter,
<false, Seq_RAIter, _RAIter, _Compare, _RAIter, _Compare, _DiffType>
DiffType> {
{ void operator()(const Seq_RAIter& __seqs_begin,
void operator()(const Seq_RAIter& __seqs_begin,
const Seq_RAIter& __seqs_end, const Seq_RAIter& __seqs_end,
const _RAIter& __target, const _RAIter& __target,
_Compare& __comp, _Compare& __comp,
DiffType __length_am) const _DiffType __length_am) const
{ {
multiway_merge(__seqs_begin, __seqs_end, __target, __length_am, __comp, multiway_merge(__seqs_begin, __seqs_end, __target, __length_am, __comp,
sequential_tag()); sequential_tag());
} }
}; };
/** @brief PMWMS code executed by each thread.
* @param __sd Pointer to algorithm data.
* @param __comp Comparator.
*/
template<bool __stable, bool __exact, typename _RAIter,
typename _Compare>
void
parallel_sort_mwms_pu(_PMWMSSortingData<_RAIter>* __sd,
_Compare& __comp)
{
typedef std::iterator_traits<_RAIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType;
/** @brief PMWMS code executed by each thread. _ThreadIndex __iam = omp_get_thread_num();
* @param __sd Pointer to algorithm data.
* @param __comp Comparator. // Length of this thread's chunk, before merging.
*/ _DifferenceType __length_local
template<bool __stable, bool __exact, typename _RAIter, = __sd->_M_starts[__iam + 1] - __sd->_M_starts[__iam];
typename _Compare>
void // Sort in temporary storage, leave space for sentinel.
parallel_sort_mwms_pu(_PMWMSSortingData<_RAIter>* __sd,
_Compare& __comp) typedef _ValueType* _SortingPlacesIterator;
{
typedef std::iterator_traits<_RAIter> _TraitsType; __sd->_M_temporary[__iam] =
typedef typename _TraitsType::value_type _ValueType; static_cast<_ValueType*>(::operator new(sizeof(_ValueType)
typedef typename _TraitsType::difference_type _DifferenceType; * (__length_local + 1)));
_ThreadIndex __iam = omp_get_thread_num(); // Copy there.
std::uninitialized_copy(__sd->_M_source + __sd->_M_starts[__iam],
// Length of this thread's chunk, before merging. __sd->_M_source + __sd->_M_starts[__iam]
_DifferenceType __length_local + __length_local,
= __sd->_M_starts[__iam + 1] - __sd->_M_starts[__iam]; __sd->_M_temporary[__iam]);
// Sort in temporary storage, leave space for sentinel. __possibly_stable_sort<__stable, _SortingPlacesIterator, _Compare>()
typedef _ValueType* _SortingPlacesIterator;
__sd->_M_temporary[__iam] =
static_cast<_ValueType*>(
::operator new(sizeof(_ValueType) * (__length_local + 1)));
// Copy there.
std::uninitialized_copy(
__sd->_M_source + __sd->_M_starts[__iam],
__sd->_M_source + __sd->_M_starts[__iam] + __length_local,
__sd->_M_temporary[__iam]);
__possibly_stable_sort<__stable, _SortingPlacesIterator, _Compare>()
(__sd->_M_temporary[__iam], (__sd->_M_temporary[__iam],
__sd->_M_temporary[__iam] + __length_local, __sd->_M_temporary[__iam] + __length_local,
__comp); __comp);
// Invariant: locally sorted subsequence in sd->_M_temporary[__iam], // Invariant: locally sorted subsequence in sd->_M_temporary[__iam],
// __sd->_M_temporary[__iam] + __length_local. // __sd->_M_temporary[__iam] + __length_local.
// No barrier here: Synchronization is done by the splitting routine. // No barrier here: Synchronization is done by the splitting routine.
_DifferenceType __num_samples = _DifferenceType __num_samples =
_Settings::get().sort_mwms_oversampling * __sd->_M_num_threads - 1; _Settings::get().sort_mwms_oversampling * __sd->_M_num_threads - 1;
_SplitConsistently _SplitConsistently
<__exact, _RAIter, _Compare, _SortingPlacesIterator>() <__exact, _RAIter, _Compare, _SortingPlacesIterator>()
(__iam, __sd, __comp, __num_samples); (__iam, __sd, __comp, __num_samples);
// Offset from __target __begin, __length after merging. // Offset from __target __begin, __length after merging.
_DifferenceType __offset = 0, __length_am = 0; _DifferenceType __offset = 0, __length_am = 0;
for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; __s++) for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; __s++)
{ {
__length_am += __sd->_M_pieces[__iam][__s]._M_end __length_am += (__sd->_M_pieces[__iam][__s]._M_end
- __sd->_M_pieces[__iam][__s]._M_begin; - __sd->_M_pieces[__iam][__s]._M_begin);
__offset += __sd->_M_pieces[__iam][__s]._M_begin; __offset += __sd->_M_pieces[__iam][__s]._M_begin;
} }
typedef std::vector< typedef std::vector<
std::pair<_SortingPlacesIterator, _SortingPlacesIterator> > std::pair<_SortingPlacesIterator, _SortingPlacesIterator> >
_SeqVector; _SeqVector;
_SeqVector seqs(__sd->_M_num_threads); _SeqVector seqs(__sd->_M_num_threads);
for (int __s = 0; __s < __sd->_M_num_threads; ++__s) for (int __s = 0; __s < __sd->_M_num_threads; ++__s)
{ {
seqs[__s] = seqs[__s] =
std::make_pair( std::make_pair
__sd->_M_temporary[__s] + __sd->_M_pieces[__iam][__s]._M_begin, (__sd->_M_temporary[__s] + __sd->_M_pieces[__iam][__s]._M_begin,
__sd->_M_temporary[__s] + __sd->_M_pieces[__iam][__s]._M_end); __sd->_M_temporary[__s] + __sd->_M_pieces[__iam][__s]._M_end);
} }
__possibly_stable_multiway_merge< __possibly_stable_multiway_merge<
__stable, __stable,
typename _SeqVector::iterator, typename _SeqVector::iterator,
_RAIter, _RAIter,
_Compare, _DifferenceType>() _Compare, _DifferenceType>()
(seqs.begin(), seqs.end(), (seqs.begin(), seqs.end(),
__sd->_M_source + __offset, __comp, __sd->_M_source + __offset, __comp,
__length_am); __length_am);
# pragma omp barrier # pragma omp barrier
::operator delete(__sd->_M_temporary[__iam]); ::operator delete(__sd->_M_temporary[__iam]);
} }
/** @brief PMWMS main call. /** @brief PMWMS main call.
* @param __begin Begin iterator of sequence. * @param __begin Begin iterator of sequence.
* @param __end End iterator of sequence. * @param __end End iterator of sequence.
* @param __comp Comparator. * @param __comp Comparator.
* @param __n Length of sequence. * @param __n Length of sequence.
* @param __num_threads Number of threads to use. * @param __num_threads Number of threads to use.
*/ */
template<bool __stable, bool __exact, typename _RAIter, template<bool __stable, bool __exact, typename _RAIter,
typename _Compare> typename _Compare>
void void
parallel_sort_mwms(_RAIter __begin, _RAIter __end, parallel_sort_mwms(_RAIter __begin, _RAIter __end,
_Compare __comp, _Compare __comp,
_ThreadIndex __num_threads) _ThreadIndex __num_threads)
{ {
_GLIBCXX_CALL(__end - __begin) _GLIBCXX_CALL(__end - __begin)
typedef std::iterator_traits<_RAIter> _TraitsType; typedef std::iterator_traits<_RAIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType; typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType; typedef typename _TraitsType::difference_type _DifferenceType;
_DifferenceType __n = __end - __begin; _DifferenceType __n = __end - __begin;
if (__n <= 1) if (__n <= 1)
return; return;
// at least one element per thread // at least one element per thread
if (__num_threads > __n) if (__num_threads > __n)
__num_threads = static_cast<_ThreadIndex>(__n); __num_threads = static_cast<_ThreadIndex>(__n);
// shared variables // shared variables
_PMWMSSortingData<_RAIter> __sd; _PMWMSSortingData<_RAIter> __sd;
_DifferenceType* _M_starts; _DifferenceType* _M_starts;
# pragma omp parallel num_threads(__num_threads) # pragma omp parallel num_threads(__num_threads)
{ {
__num_threads = omp_get_num_threads(); //no more threads than requested __num_threads = omp_get_num_threads(); //no more threads than requested
# pragma omp single # pragma omp single
{ {
__sd._M_num_threads = __num_threads; __sd._M_num_threads = __num_threads;
__sd._M_source = __begin; __sd._M_source = __begin;
__sd._M_temporary = new _ValueType*[__num_threads]; __sd._M_temporary = new _ValueType*[__num_threads];
if (!__exact) if (!__exact)
{ {
_DifferenceType __size = _DifferenceType __size =
(_Settings::get().sort_mwms_oversampling * __num_threads - 1) (_Settings::get().sort_mwms_oversampling * __num_threads - 1)
* __num_threads; * __num_threads;
__sd._M_samples = static_cast<_ValueType*>( __sd._M_samples = static_cast<_ValueType*>
::operator new(__size * sizeof(_ValueType))); (::operator new(__size * sizeof(_ValueType)));
} }
else else
__sd._M_samples = NULL; __sd._M_samples = NULL;
__sd._M_offsets = new _DifferenceType[__num_threads - 1]; __sd._M_offsets = new _DifferenceType[__num_threads - 1];
__sd._M_pieces __sd._M_pieces
= new std::vector<_Piece<_DifferenceType> >[__num_threads]; = new std::vector<_Piece<_DifferenceType> >[__num_threads];
for (int __s = 0; __s < __num_threads; ++__s) for (int __s = 0; __s < __num_threads; ++__s)
__sd._M_pieces[__s].resize(__num_threads); __sd._M_pieces[__s].resize(__num_threads);
_M_starts = __sd._M_starts _M_starts = __sd._M_starts
= new _DifferenceType[__num_threads + 1]; = new _DifferenceType[__num_threads + 1];
_DifferenceType __chunk_length = __n / __num_threads; _DifferenceType __chunk_length = __n / __num_threads;
_DifferenceType __split = __n % __num_threads; _DifferenceType __split = __n % __num_threads;
_DifferenceType __pos = 0; _DifferenceType __pos = 0;
for (int __i = 0; __i < __num_threads; ++__i) for (int __i = 0; __i < __num_threads; ++__i)
{ {
_M_starts[__i] = __pos; _M_starts[__i] = __pos;
__pos += (__i < __split) __pos += (__i < __split)
? (__chunk_length + 1) : __chunk_length; ? (__chunk_length + 1) : __chunk_length;
} }
_M_starts[__num_threads] = __pos; _M_starts[__num_threads] = __pos;
} //single } //single
// Now sort in parallel. // Now sort in parallel.
parallel_sort_mwms_pu<__stable, __exact>(&__sd, __comp); parallel_sort_mwms_pu<__stable, __exact>(&__sd, __comp);
} //parallel } //parallel
delete[] _M_starts; delete[] _M_starts;
delete[] __sd._M_temporary; delete[] __sd._M_temporary;
if (!__exact) if (!__exact)
::operator delete(__sd._M_samples); ::operator delete(__sd._M_samples);
delete[] __sd._M_offsets; delete[] __sd._M_offsets;
delete[] __sd._M_pieces; delete[] __sd._M_pieces;
} }
} //namespace __gnu_parallel } //namespace __gnu_parallel
#endif /* _GLIBCXX_PARALLEL_MULTIWAY_MERGESORT_H */ #endif /* _GLIBCXX_PARALLEL_MULTIWAY_MERGESORT_H */
...@@ -41,74 +41,74 @@ ...@@ -41,74 +41,74 @@
namespace __gnu_parallel namespace __gnu_parallel
{ {
/** @brief Embarrassingly parallel algorithm for random access /** @brief Embarrassingly parallel algorithm for random access
* iterators, using an OpenMP for loop. * iterators, using an OpenMP for loop.
* *
* @param __begin Begin iterator of element sequence. * @param __begin Begin iterator of element sequence.
* @param __end End iterator of element sequence. * @param __end End iterator of element sequence.
* @param __o User-supplied functor (comparator, predicate, adding * @param __o User-supplied functor (comparator, predicate, adding
* functor, etc.). * functor, etc.).
* @param __f Functor to "process" an element with __op (depends on * @param __f Functor to "process" an element with __op (depends on
* desired functionality, e. g. for std::for_each(), ...). * desired functionality, e. g. for std::for_each(), ...).
* @param __r Functor to "add" a single __result to the already * @param __r Functor to "add" a single __result to the already
* processed elements (depends on functionality). * processed elements (depends on functionality).
* @param __base Base value for reduction. * @param __base Base value for reduction.
* @param __output Pointer to position where final result is written to * @param __output Pointer to position where final result is written to
* @param __bound Maximum number of elements processed (e. g. for * @param __bound Maximum number of elements processed (e. g. for
* std::count_n()). * std::count_n()).
* @return User-supplied functor (that may contain a part of the result). * @return User-supplied functor (that may contain a part of the result).
*/ */
template<typename _RAIter, template<typename _RAIter,
typename _Op, typename _Op,
typename _Fu, typename _Fu,
typename _Red, typename _Red,
typename _Result> typename _Result>
_Op _Op
__for_each_template_random_access_omp_loop( __for_each_template_random_access_omp_loop(_RAIter __begin, _RAIter __end,
_RAIter __begin, _RAIter __end, _Op __o, _Fu& __f, _Red __r, _Op __o, _Fu& __f, _Red __r,
_Result __base, _Result& __output, _Result __base,
typename std::iterator_traits<_RAIter>::difference_type __bound) _Result& __output,
{ typename std::iterator_traits<_RAIter>::difference_type __bound)
typedef typename {
std::iterator_traits<_RAIter>::difference_type typedef typename std::iterator_traits<_RAIter>::difference_type
_DifferenceType; _DifferenceType;
_DifferenceType __length = __end - __begin; _DifferenceType __length = __end - __begin;
_ThreadIndex __num_threads = _ThreadIndex __num_threads =
__gnu_parallel::min<_DifferenceType>(__get_max_threads(), __length); __gnu_parallel::min<_DifferenceType>(__get_max_threads(), __length);
_Result *__thread_results; _Result *__thread_results;
# pragma omp parallel num_threads(__num_threads) # pragma omp parallel num_threads(__num_threads)
{ {
# pragma omp single # pragma omp single
{ {
__num_threads = omp_get_num_threads(); __num_threads = omp_get_num_threads();
__thread_results = new _Result[__num_threads]; __thread_results = new _Result[__num_threads];
for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
__thread_results[__i] = _Result(); __thread_results[__i] = _Result();
} }
_ThreadIndex __iam = omp_get_thread_num(); _ThreadIndex __iam = omp_get_thread_num();
#pragma omp for schedule(dynamic, _Settings::get().workstealing_chunk_size) #pragma omp for schedule(dynamic, _Settings::get().workstealing_chunk_size)
for (_DifferenceType __pos = 0; __pos < __length; ++__pos) for (_DifferenceType __pos = 0; __pos < __length; ++__pos)
__thread_results[__iam] = __thread_results[__iam] =
__r(__thread_results[__iam], __f(__o, __begin+__pos)); __r(__thread_results[__iam], __f(__o, __begin+__pos));
} //parallel } //parallel
for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
__output = __r(__output, __thread_results[__i]); __output = __r(__output, __thread_results[__i]);
delete [] __thread_results; delete [] __thread_results;
// Points to last element processed (needed as return value for // Points to last element processed (needed as return value for
// some algorithms like transform). // some algorithms like transform).
__f._M_finish_iterator = __begin + __length; __f._M_finish_iterator = __begin + __length;
return __o; return __o;
} }
} // end namespace } // end namespace
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
namespace __gnu_parallel namespace __gnu_parallel
{ {
/** @brief Embarrassingly parallel algorithm for random access /** @brief Embarrassingly parallel algorithm for random access
* iterators, using an OpenMP for loop with static scheduling. * iterators, using an OpenMP for loop with static scheduling.
* *
...@@ -58,37 +57,38 @@ namespace __gnu_parallel ...@@ -58,37 +57,38 @@ namespace __gnu_parallel
* std::count_n()). * std::count_n()).
* @return User-supplied functor (that may contain a part of the result). * @return User-supplied functor (that may contain a part of the result).
*/ */
template<typename _RAIter, template<typename _RAIter,
typename _Op, typename _Op,
typename _Fu, typename _Fu,
typename _Red, typename _Red,
typename _Result> typename _Result>
_Op _Op
__for_each_template_random_access_omp_loop_static( __for_each_template_random_access_omp_loop_static(_RAIter __begin,
_RAIter __begin, _RAIter __end, _Op __o, _Fu& __f, _Red __r, _RAIter __end, _Op __o,
_Result __base, _Result& __output, _Fu& __f, _Red __r,
typename std::iterator_traits<_RAIter>::difference_type __bound) _Result __base,
{ _Result& __output,
typedef typename typename std::iterator_traits<_RAIter>::difference_type __bound)
std::iterator_traits<_RAIter>::difference_type {
_DifferenceType; typedef typename std::iterator_traits<_RAIter>::difference_type
_DifferenceType;
_DifferenceType __length = __end - __begin;
_ThreadIndex __num_threads = _DifferenceType __length = __end - __begin;
std::min<_DifferenceType>(__get_max_threads(), __length); _ThreadIndex __num_threads =
std::min<_DifferenceType>(__get_max_threads(), __length);
_Result *__thread_results;
_Result *__thread_results;
# pragma omp parallel num_threads(__num_threads)
# pragma omp parallel num_threads(__num_threads)
{ {
# pragma omp single # pragma omp single
{ {
__num_threads = omp_get_num_threads(); __num_threads = omp_get_num_threads();
__thread_results = new _Result[__num_threads]; __thread_results = new _Result[__num_threads];
for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
__thread_results[__i] = _Result(); __thread_results[__i] = _Result();
} }
_ThreadIndex __iam = omp_get_thread_num(); _ThreadIndex __iam = omp_get_thread_num();
...@@ -98,17 +98,17 @@ template<typename _RAIter, ...@@ -98,17 +98,17 @@ template<typename _RAIter,
__f(__o, __begin+__pos)); __f(__o, __begin+__pos));
} //parallel } //parallel
for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
__output = __r(__output, __thread_results[__i]); __output = __r(__output, __thread_results[__i]);
delete [] __thread_results; delete [] __thread_results;
// Points to last element processed (needed as return value for // Points to last element processed (needed as return value for
// some algorithms like transform). // some algorithms like transform).
__f.finish_iterator = __begin + __length; __f.finish_iterator = __begin + __length;
return __o; return __o;
} }
} // end namespace } // end namespace
......
...@@ -40,94 +40,93 @@ ...@@ -40,94 +40,93 @@
namespace __gnu_parallel namespace __gnu_parallel
{ {
/** @brief Embarrassingly parallel algorithm for random access
/** @brief Embarrassingly parallel algorithm for random access * iterators, using hand-crafted parallelization by equal splitting
* iterators, using hand-crafted parallelization by equal splitting * the work.
* the work. *
* * @param __begin Begin iterator of element sequence.
* @param __begin Begin iterator of element sequence. * @param __end End iterator of element sequence.
* @param __end End iterator of element sequence. * @param __o User-supplied functor (comparator, predicate, adding
* @param __o User-supplied functor (comparator, predicate, adding * functor, ...)
* functor, ...) * @param __f Functor to "process" an element with __op (depends on
* @param __f Functor to "process" an element with __op (depends on * desired functionality, e. g. for std::for_each(), ...).
* desired functionality, e. g. for std::for_each(), ...). * @param __r Functor to "add" a single __result to the already
* @param __r Functor to "add" a single __result to the already * processed elements (depends on functionality).
* processed elements (depends on functionality). * @param __base Base value for reduction.
* @param __base Base value for reduction. * @param __output Pointer to position where final result is written to
* @param __output Pointer to position where final result is written to * @param __bound Maximum number of elements processed (e. g. for
* @param __bound Maximum number of elements processed (e. g. for * std::count_n()).
* std::count_n()). * @return User-supplied functor (that may contain a part of the result).
* @return User-supplied functor (that may contain a part of the result). */
*/ template<typename _RAIter,
template<typename _RAIter, typename _Op,
typename _Op, typename _Fu,
typename _Fu, typename _Red,
typename _Red, typename _Result>
typename _Result> _Op
_Op __for_each_template_random_access_ed(_RAIter __begin, _RAIter __end,
__for_each_template_random_access_ed( _Op __o, _Fu& __f, _Red __r,
_RAIter __begin, _RAIter __end, _Op __o, _Fu& __f, _Red __r, _Result __base, _Result& __output,
_Result __base, _Result& __output, typename std::iterator_traits<_RAIter>::difference_type __bound)
typename std::iterator_traits<_RAIter>::difference_type __bound) {
{ typedef std::iterator_traits<_RAIter> _TraitsType;
typedef std::iterator_traits<_RAIter> _TraitsType; typedef typename _TraitsType::difference_type _DifferenceType;
typedef typename _TraitsType::difference_type _DifferenceType; const _DifferenceType __length = __end - __begin;
const _DifferenceType __length = __end - __begin; _Result *__thread_results;
_Result *__thread_results; bool* __constructed;
bool* __constructed;
_ThreadIndex __num_threads =
_ThreadIndex __num_threads = __gnu_parallel::min<_DifferenceType>(__get_max_threads(), __length);
__gnu_parallel::min<_DifferenceType>(__get_max_threads(), __length);
# pragma omp parallel num_threads(__num_threads)
# pragma omp parallel num_threads(__num_threads)
{ {
# pragma omp single # pragma omp single
{ {
__num_threads = omp_get_num_threads(); __num_threads = omp_get_num_threads();
__thread_results = __thread_results =
static_cast<_Result*>( static_cast<_Result*>(::operator new(__num_threads
::operator new(__num_threads * sizeof(_Result))); * sizeof(_Result)));
__constructed = new bool[__num_threads]; __constructed = new bool[__num_threads];
} }
_ThreadIndex __iam = omp_get_thread_num(); _ThreadIndex __iam = omp_get_thread_num();
// Neutral element. // Neutral element.
_Result* __reduct = _Result* __reduct =
static_cast<_Result*>(::operator new(sizeof(_Result))); static_cast<_Result*>(::operator new(sizeof(_Result)));
_DifferenceType _DifferenceType
__start = equally_split_point(__length, __num_threads, __iam), __start = equally_split_point(__length, __num_threads, __iam),
__stop = equally_split_point(__length, __num_threads, __iam + 1); __stop = equally_split_point(__length, __num_threads, __iam + 1);
if (__start < __stop) if (__start < __stop)
{ {
new(__reduct) _Result(__f(__o, __begin + __start)); new(__reduct) _Result(__f(__o, __begin + __start));
++__start; ++__start;
__constructed[__iam] = true; __constructed[__iam] = true;
} }
else else
__constructed[__iam] = false; __constructed[__iam] = false;
for (; __start < __stop; ++__start) for (; __start < __stop; ++__start)
*__reduct = __r(*__reduct, __f(__o, __begin + __start)); *__reduct = __r(*__reduct, __f(__o, __begin + __start));
__thread_results[__iam] = *__reduct; __thread_results[__iam] = *__reduct;
} //parallel } //parallel
for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
if (__constructed[__i]) if (__constructed[__i])
__output = __r(__output, __thread_results[__i]); __output = __r(__output, __thread_results[__i]);
// Points to last element processed (needed as return value for // Points to last element processed (needed as return value for
// some algorithms like transform). // some algorithms like transform).
__f._M_finish_iterator = __begin + __length; __f._M_finish_iterator = __begin + __length;
delete[] __thread_results; delete[] __thread_results;
delete[] __constructed; delete[] __constructed;
return __o; return __o;
} }
} // end namespace } // end namespace
......
...@@ -43,106 +43,107 @@ namespace __gnu_parallel ...@@ -43,106 +43,107 @@ namespace __gnu_parallel
{ {
// Problem: there is no 0-element given. // Problem: there is no 0-element given.
/** @brief Base case prefix sum routine. /** @brief Base case prefix sum routine.
* @param __begin Begin iterator of input sequence. * @param __begin Begin iterator of input sequence.
* @param __end End iterator of input sequence. * @param __end End iterator of input sequence.
* @param __result Begin iterator of output sequence. * @param __result Begin iterator of output sequence.
* @param __bin_op Associative binary function. * @param __bin_op Associative binary function.
* @param __value Start value. Must be passed since the neutral * @param __value Start value. Must be passed since the neutral
* element is unknown in general. * element is unknown in general.
* @return End iterator of output sequence. */ * @return End iterator of output sequence. */
template<typename _IIter, template<typename _IIter,
typename _OutputIterator, typename _OutputIterator,
typename _BinaryOperation> typename _BinaryOperation>
_OutputIterator _OutputIterator
__parallel_partial_sum_basecase( __parallel_partial_sum_basecase(_IIter __begin, _IIter __end,
_IIter __begin, _IIter __end, _OutputIterator __result, _OutputIterator __result,
_BinaryOperation __bin_op, _BinaryOperation __bin_op,
typename std::iterator_traits <_IIter>::value_type __value) typename std::iterator_traits <_IIter>::value_type __value)
{ {
if (__begin == __end) if (__begin == __end)
return __result;
while (__begin != __end)
{
__value = __bin_op(__value, *__begin);
*__result = __value;
++__result;
++__begin;
}
return __result; return __result;
}
while (__begin != __end)
{ /** @brief Parallel partial sum implementation, two-phase approach,
__value = __bin_op(__value, *__begin); no recursion.
*__result = __value; * @param __begin Begin iterator of input sequence.
++__result; * @param __end End iterator of input sequence.
++__begin; * @param __result Begin iterator of output sequence.
} * @param __bin_op Associative binary function.
return __result; * @param __n Length of sequence.
} * @param __num_threads Number of threads to use.
* @return End iterator of output sequence.
/** @brief Parallel partial sum implementation, two-phase approach, */
no recursion. template<typename _IIter,
* @param __begin Begin iterator of input sequence. typename _OutputIterator,
* @param __end End iterator of input sequence. typename _BinaryOperation>
* @param __result Begin iterator of output sequence. _OutputIterator
* @param __bin_op Associative binary function. __parallel_partial_sum_linear(_IIter __begin, _IIter __end,
* @param __n Length of sequence. _OutputIterator __result,
* @param __num_threads Number of threads to use. _BinaryOperation __bin_op,
* @return End iterator of output sequence. typename std::iterator_traits<_IIter>::difference_type __n)
*/ {
template<typename _IIter, typedef std::iterator_traits<_IIter> _TraitsType;
typename _OutputIterator, typedef typename _TraitsType::value_type _ValueType;
typename _BinaryOperation> typedef typename _TraitsType::difference_type _DifferenceType;
_OutputIterator
__parallel_partial_sum_linear( if (__begin == __end)
_IIter __begin, _IIter __end, _OutputIterator __result, return __result;
_BinaryOperation __bin_op,
typename std::iterator_traits<_IIter>::difference_type __n) _ThreadIndex __num_threads =
{
typedef std::iterator_traits<_IIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType;
if (__begin == __end)
return __result;
_ThreadIndex __num_threads =
std::min<_DifferenceType>(__get_max_threads(), __n - 1); std::min<_DifferenceType>(__get_max_threads(), __n - 1);
if (__num_threads < 2) if (__num_threads < 2)
{ {
*__result = *__begin; *__result = *__begin;
return __parallel_partial_sum_basecase( return __parallel_partial_sum_basecase(__begin + 1, __end,
__begin + 1, __end, __result + 1, __bin_op, *__begin); __result + 1, __bin_op,
} *__begin);
}
_DifferenceType* __borders; _DifferenceType* __borders;
_ValueType* __sums; _ValueType* __sums;
const _Settings& __s = _Settings::get(); const _Settings& __s = _Settings::get();
# pragma omp parallel num_threads(__num_threads) # pragma omp parallel num_threads(__num_threads)
{ {
# pragma omp single # pragma omp single
{ {
__num_threads = omp_get_num_threads(); __num_threads = omp_get_num_threads();
__borders = new _DifferenceType[__num_threads + 2]; __borders = new _DifferenceType[__num_threads + 2];
if (__s.partial_sum_dilation == 1.0f) if (__s.partial_sum_dilation == 1.0f)
equally_split(__n, __num_threads + 1, __borders); equally_split(__n, __num_threads + 1, __borders);
else else
{ {
_DifferenceType __chunk_length = _DifferenceType __chunk_length =
((double)__n ((double)__n
/ ((double)__num_threads + __s.partial_sum_dilation)), / ((double)__num_threads + __s.partial_sum_dilation)),
__borderstart = __n - __num_threads * __chunk_length; __borderstart = __n - __num_threads * __chunk_length;
__borders[0] = 0; __borders[0] = 0;
for (int __i = 1; __i < (__num_threads + 1); ++__i) for (int __i = 1; __i < (__num_threads + 1); ++__i)
{ {
__borders[__i] = __borderstart; __borders[__i] = __borderstart;
__borderstart += __chunk_length; __borderstart += __chunk_length;
} }
__borders[__num_threads + 1] = __n; __borders[__num_threads + 1] = __n;
} }
__sums = static_cast<_ValueType*>(::operator new(sizeof(_ValueType) __sums = static_cast<_ValueType*>(::operator new(sizeof(_ValueType)
* __num_threads)); * __num_threads));
_OutputIterator __target_end; _OutputIterator __target_end;
} //single } //single
_ThreadIndex __iam = omp_get_thread_num(); _ThreadIndex __iam = omp_get_thread_num();
if (__iam == 0) if (__iam == 0)
...@@ -166,58 +167,57 @@ template<typename _IIter, ...@@ -166,58 +167,57 @@ template<typename _IIter,
# pragma omp barrier # pragma omp barrier
# pragma omp single # pragma omp single
__parallel_partial_sum_basecase(__sums + 1, __sums + __num_threads, __parallel_partial_sum_basecase(__sums + 1, __sums + __num_threads,
__sums + 1, __bin_op, __sums[0]); __sums + 1, __bin_op, __sums[0]);
# pragma omp barrier # pragma omp barrier
// Still same team. // Still same team.
__parallel_partial_sum_basecase( __parallel_partial_sum_basecase(__begin + __borders[__iam + 1],
__begin + __borders[__iam + 1], __begin + __borders[__iam + 2],
__begin + __borders[__iam + 2], __result + __borders[__iam + 1],
__result + __borders[__iam + 1], __bin_op, __sums[__iam]);
__bin_op, __sums[__iam]);
} //parallel } //parallel
::operator delete(__sums); ::operator delete(__sums);
delete[] __borders; delete[] __borders;
return __result + __n; return __result + __n;
} }
/** @brief Parallel partial sum front-__end. /** @brief Parallel partial sum front-__end.
* @param __begin Begin iterator of input sequence. * @param __begin Begin iterator of input sequence.
* @param __end End iterator of input sequence. * @param __end End iterator of input sequence.
* @param __result Begin iterator of output sequence. * @param __result Begin iterator of output sequence.
* @param __bin_op Associative binary function. * @param __bin_op Associative binary function.
* @return End iterator of output sequence. */ * @return End iterator of output sequence. */
template<typename _IIter, template<typename _IIter,
typename _OutputIterator, typename _OutputIterator,
typename _BinaryOperation> typename _BinaryOperation>
_OutputIterator _OutputIterator
__parallel_partial_sum(_IIter __begin, _IIter __end, __parallel_partial_sum(_IIter __begin, _IIter __end,
_OutputIterator __result, _BinaryOperation __bin_op) _OutputIterator __result, _BinaryOperation __bin_op)
{ {
_GLIBCXX_CALL(__begin - __end) _GLIBCXX_CALL(__begin - __end)
typedef std::iterator_traits<_IIter> _TraitsType; typedef std::iterator_traits<_IIter> _TraitsType;
typedef typename _TraitsType::value_type _ValueType; typedef typename _TraitsType::value_type _ValueType;
typedef typename _TraitsType::difference_type _DifferenceType; typedef typename _TraitsType::difference_type _DifferenceType;
_DifferenceType __n = __end - __begin; _DifferenceType __n = __end - __begin;
switch (_Settings::get().partial_sum_algorithm) switch (_Settings::get().partial_sum_algorithm)
{ {
case LINEAR: case LINEAR:
// Need an initial offset. // Need an initial offset.
return __parallel_partial_sum_linear( return __parallel_partial_sum_linear(__begin, __end, __result,
__begin, __end, __result, __bin_op, __n); __bin_op, __n);
default: default:
// Partial_sum algorithm not implemented. // Partial_sum algorithm not implemented.
_GLIBCXX_PARALLEL_ASSERT(0); _GLIBCXX_PARALLEL_ASSERT(0);
return __result + __n; return __result + __n;
} }
} }
} }
#endif /* _GLIBCXX_PARALLEL_PARTIAL_SUM_H */ #endif /* _GLIBCXX_PARALLEL_PARTIAL_SUM_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment