diff options
Diffstat (limited to 'libstdc++-v3/include')
93 files changed, 9601 insertions, 8683 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index f3dcd19b79f..1cea8a24e94 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -121,6 +121,7 @@ bits_headers = \ ${bits_srcdir}/stream_iterator.h \ ${bits_srcdir}/streambuf_iterator.h \ ${bits_srcdir}/shared_ptr.h \ + ${bits_srcdir}/shared_ptr_base.h \ ${bits_srcdir}/slice_array.h \ ${bits_srcdir}/sstream.tcc \ ${bits_srcdir}/stl_algo.h \ @@ -618,6 +619,11 @@ tr1_impl_headers = \ ${tr1_impl_srcdir}/unordered_set \ ${tr1_impl_srcdir}/utility +decimal_srcdir = ${glibcxx_srcdir}/include/decimal +decimal_builddir = ./decimal +decimal_headers = \ + ${decimal_srcdir}/decimal \ + ${decimal_srcdir}/decimal.h # This is the common subset of C++ files that all three "C" header models use. c_base_srcdir = $(C_INCLUDE_DIR) @@ -896,8 +902,8 @@ endif allstamped = \ stamp-std stamp-bits stamp-c_base stamp-c_base_extra \ stamp-c_compatibility stamp-backward stamp-ext stamp-pb \ - stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host \ - stamp-profile stamp-profile-impl + stamp-tr1 stamp-tr1-impl stamp-decimal stamp-debug \ + stamp-parallel stamp-profile stamp-profile-impl stamp-host # List of all files that are created by explicit building, editing, or # catenation. @@ -1011,6 +1017,11 @@ stamp-tr1-impl: ${tr1_impl_headers} @-cd ${tr1_impl_builddir} && $(LN_S) $? . 2>/dev/null @$(STAMP) stamp-tr1-impl +stamp-decimal: ${decimal_headers} + @-mkdir -p ${decimal_builddir} + @-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null + @$(STAMP) stamp-decimal + stamp-debug: ${debug_headers} @-mkdir -p ${debug_builddir} @-cd ${debug_builddir} && $(LN_S) $? . 2>/dev/null @@ -1239,6 +1250,9 @@ install-headers: $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_impl_builddir} for file in ${tr1_impl_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_impl_builddir}; done + $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir} + for file in ${decimal_headers}; do \ + $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir} for file in ${c_base_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${c_base_builddir}; done @@ -1283,9 +1297,10 @@ clean-local: # directory. (This is more of an example of how this kind of rule can # be made.) .PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr1_impl_headers) - $(ext_headers) + $(decimal_headers) $(ext_headers) $(std_headers): ; @: $(c_base_headers): ; @: $(tr1_headers): ; @: $(tr1_impl_headers): ; @: +$(decimal_headers): ; @: $(ext_headers): ; @: diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 4c69a2be288..fa741a59bd1 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -14,6 +14,8 @@ # PARTICULAR PURPOSE. @SET_MAKE@ + +#o# Makefile for the include subdirectory of the GNU C++ Standard library. VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ @@ -362,6 +364,7 @@ bits_headers = \ ${bits_srcdir}/stream_iterator.h \ ${bits_srcdir}/streambuf_iterator.h \ ${bits_srcdir}/shared_ptr.h \ + ${bits_srcdir}/shared_ptr_base.h \ ${bits_srcdir}/slice_array.h \ ${bits_srcdir}/sstream.tcc \ ${bits_srcdir}/stl_algo.h \ @@ -856,6 +859,12 @@ tr1_impl_headers = \ ${tr1_impl_srcdir}/unordered_set \ ${tr1_impl_srcdir}/utility +decimal_srcdir = ${glibcxx_srcdir}/include/decimal +decimal_builddir = ./decimal +decimal_headers = \ + ${decimal_srcdir}/decimal \ + ${decimal_srcdir}/decimal.h + # This is the common subset of C++ files that all three "C" header models use. c_base_srcdir = $(C_INCLUDE_DIR) @@ -1001,25 +1010,25 @@ parallel_builddir = ./parallel @ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/unique_copy.h \ @ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/workstealing.h - # Profile mode headers profile_srcdir = ${glibcxx_srcdir}/include/profile profile_builddir = ./profile profile_headers = \ - ${profile_srcdir}/base.h \ - ${profile_srcdir}/unordered_map \ - ${profile_srcdir}/unordered_set \ - ${profile_srcdir}/vector \ - ${profile_srcdir}/bitset \ - ${profile_srcdir}/deque \ - ${profile_srcdir}/list \ - ${profile_srcdir}/map \ - ${profile_srcdir}/map.h \ - ${profile_srcdir}/multimap.h \ - ${profile_srcdir}/multiset.h \ - ${profile_srcdir}/set \ - ${profile_srcdir}/set.h \ - ${profile_srcdir}/hashtable.h + ${profile_srcdir}/base.h \ + ${profile_srcdir}/unordered_map \ + ${profile_srcdir}/unordered_set \ + ${profile_srcdir}/vector \ + ${profile_srcdir}/bitset \ + ${profile_srcdir}/deque \ + ${profile_srcdir}/list \ + ${profile_srcdir}/map \ + ${profile_srcdir}/map.h \ + ${profile_srcdir}/multimap.h \ + ${profile_srcdir}/multiset.h \ + ${profile_srcdir}/set \ + ${profile_srcdir}/set.h \ + ${profile_srcdir}/hashtable.h + profile_impl_srcdir = ${glibcxx_srcdir}/include/profile/impl profile_impl_builddir = ./profile/impl profile_impl_headers = \ @@ -1116,8 +1125,8 @@ PCHFLAGS = -x c++-header $(CXXFLAGS) allstamped = \ stamp-std stamp-bits stamp-c_base stamp-c_base_extra \ stamp-c_compatibility stamp-backward stamp-ext stamp-pb \ - stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host \ - stamp-profile stamp-profile-impl + stamp-tr1 stamp-tr1-impl stamp-decimal stamp-debug \ + stamp-parallel stamp-profile stamp-profile-impl stamp-host # List of all files that are created by explicit building, editing, or @@ -1424,6 +1433,11 @@ stamp-tr1-impl: ${tr1_impl_headers} @-cd ${tr1_impl_builddir} && $(LN_S) $? . 2>/dev/null @$(STAMP) stamp-tr1-impl +stamp-decimal: ${decimal_headers} + @-mkdir -p ${decimal_builddir} + @-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null + @$(STAMP) stamp-decimal + stamp-debug: ${debug_headers} @-mkdir -p ${debug_builddir} @-cd ${debug_builddir} && $(LN_S) $? . 2>/dev/null @@ -1640,6 +1654,9 @@ install-headers: $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_impl_builddir} for file in ${tr1_impl_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_impl_builddir}; done + $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir} + for file in ${decimal_headers}; do \ + $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir} for file in ${c_base_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${c_base_builddir}; done @@ -1660,8 +1677,7 @@ install-headers: $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${parallel_builddir};\ for file in $$parallel_headers_install; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${parallel_builddir}; done - $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${profile_builddir} \ - $(DESTDIR)${gxx_include_dir}/${profile_builddir}/impl + $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${profile_builddir} for file in ${profile_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${profile_builddir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${profile_impl_builddir} @@ -1682,11 +1698,12 @@ clean-local: # directory. (This is more of an example of how this kind of rule can # be made.) .PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr1_impl_headers) - $(ext_headers) + $(decimal_headers) $(ext_headers) $(std_headers): ; @: $(c_base_headers): ; @: $(tr1_headers): ; @: $(tr1_impl_headers): ; @: +$(decimal_headers): ; @: $(ext_headers): ; @: # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libstdc++-v3/include/bits/atomic_0.h b/libstdc++-v3/include/bits/atomic_0.h index a493ea66af9..0caffaf1e9f 100644 --- a/libstdc++-v3/include/bits/atomic_0.h +++ b/libstdc++-v3/include/bits/atomic_0.h @@ -82,14 +82,15 @@ namespace __atomic0 __r; }) /// atomic_flag - struct atomic_flag : private __atomic_flag_base + struct atomic_flag : public __atomic_flag_base { atomic_flag() = default; ~atomic_flag() = default; atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; - atomic_flag(bool __i) { _M_i = __i; } // XXX deleted copy ctor != agg + // Conversion to ATOMIC_FLAG_INIT. + atomic_flag(bool __i): __atomic_flag_base({ __i }) { } bool test_and_set(memory_order __m = memory_order_seq_cst) volatile; diff --git a/libstdc++-v3/include/bits/atomic_2.h b/libstdc++-v3/include/bits/atomic_2.h index 8e8e7ff16f8..d39adb920a2 100644 --- a/libstdc++-v3/include/bits/atomic_2.h +++ b/libstdc++-v3/include/bits/atomic_2.h @@ -44,14 +44,15 @@ namespace __atomic2 { /// atomic_flag - struct atomic_flag : private __atomic_flag_base + struct atomic_flag : public __atomic_flag_base { atomic_flag() = default; ~atomic_flag() = default; atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; - atomic_flag(bool __i) { _M_i = __i; } // XXX deleted copy ctor != agg + // Conversion to ATOMIC_FLAG_INIT. + atomic_flag(bool __i): __atomic_flag_base({ __i }) { } bool test_and_set(memory_order __m = memory_order_seq_cst) volatile diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index bd54537cdc1..9d44dc4fdfc 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -540,7 +540,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) basic_string& operator=(initializer_list<_CharT> __l) { - this->assign (__l.begin(), __l.end()); + this->assign(__l.begin(), __l.size()); return *this; } #endif // __GXX_EXPERIMENTAL_CXX0X__ @@ -860,7 +860,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ basic_string& operator+=(initializer_list<_CharT> __l) - { return this->append(__l.begin(), __l.end()); } + { return this->append(__l.begin(), __l.size()); } #endif // __GXX_EXPERIMENTAL_CXX0X__ /** @@ -926,7 +926,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ basic_string& append(initializer_list<_CharT> __l) - { return this->append(__l.begin(), __l.end()); } + { return this->append(__l.begin(), __l.size()); } #endif // __GXX_EXPERIMENTAL_CXX0X__ /** @@ -1045,7 +1045,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ basic_string& assign(initializer_list<_CharT> __l) - { return this->assign(__l.begin(), __l.end()); } + { return this->assign(__l.begin(), __l.size()); } #endif // __GXX_EXPERIMENTAL_CXX0X__ /** @@ -1089,7 +1089,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) */ void insert(iterator __p, initializer_list<_CharT> __l) - { this->insert(__p, __l.begin(), __l.end()); } + { + _GLIBCXX_DEBUG_PEDASSERT(__p >= _M_ibegin() && __p <= _M_iend()); + this->insert(__p - _M_ibegin(), __l.begin(), __l.size()); + } #endif // __GXX_EXPERIMENTAL_CXX0X__ /** diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 724f373ebae..f4f1f8b901f 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -147,7 +147,6 @@ # define _GLIBCXX_STD __cxx1998 # define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY_ATTR(default) { # define _GLIBCXX_END_NAMESPACE } -# define _GLIBCXX_EXTERN_TEMPLATE -1 # endif // debug + parallel @@ -172,7 +171,6 @@ # define _GLIBCXX_STD __cxx1998 # define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY_ATTR(default) { # define _GLIBCXX_END_NAMESPACE } -# define _GLIBCXX_EXTERN_TEMPLATE -1 # endif # if __NO_INLINE__ && !__GXX_WEAK__ @@ -287,6 +285,10 @@ namespace std // library to avoid multiple weak definitions for required types that // are already explicitly instantiated in the library binary. This // substantially reduces the binary size of resulting executables. + +// Special case: _GLIBCXX_EXTERN_TEMPLATE == -1 disallows extern +// templates only in basic_string, thus activating its debug-mode +// checks even at -O0. #ifndef _GLIBCXX_EXTERN_TEMPLATE # define _GLIBCXX_EXTERN_TEMPLATE 1 #endif diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 06aa6f87b91..ab661e9594c 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -32,7 +32,6 @@ namespace std { - // [26.4] Random number generation /** @@ -154,10 +153,10 @@ namespace std template<typename _UIntType, _UIntType __a, _UIntType __c, _UIntType __m> class linear_congruential_engine { - __glibcxx_class_requires(_UIntType, _UnsignedIntegerConcept) - static_assert(__m == 0 || (__a < __m && __c < __m), - "template arguments out of bounds" - " in linear_congruential_engine"); + static_assert(std::is_unsigned<_UIntType>::value, "template argument " + "substituting _UIntType not an unsigned integral type"); + static_assert(__m == 0u || (__a < __m && __c < __m), + "template argument substituting __m out of bounds"); public: /** The type of the generated random value. */ @@ -341,35 +340,32 @@ namespace std _UIntType __c, size_t __l, _UIntType __f> class mersenne_twister_engine { - __glibcxx_class_requires(_UIntType, _UnsignedIntegerConcept) - - static_assert(__m >= 1U, - "mersenne_twister_engine template arguments out of bounds"); - static_assert(__n >= __m, - "mersenne_twister_engine template arguments out of bounds"); - static_assert(__w >= __r, - "mersenne_twister_engine template arguments out of bounds"); - static_assert(__w >= __u, - "mersenne_twister_engine template arguments out of bounds"); - static_assert(__w >= __s, - "mersenne_twister_engine template arguments out of bounds"); - static_assert(__w >= __t, - "mersenne_twister_engine template arguments out of bounds"); - static_assert(__w >= __l, - "mersenne_twister_engine template arguments out of bounds"); - static_assert(__w <= - static_cast<size_t>(std::numeric_limits<_UIntType>::digits), - "mersenne_twister_engine template arguments out of bounds"); + static_assert(std::is_unsigned<_UIntType>::value, "template argument " + "substituting _UIntType not an unsigned integral type"); + static_assert(1u <= __m && __m <= __n, + "template argument substituting __m out of bounds"); + static_assert(__r <= __w, "template argument substituting " + "__r out of bound"); + static_assert(__u <= __w, "template argument substituting " + "__u out of bound"); + static_assert(__s <= __w, "template argument substituting " + "__s out of bound"); + static_assert(__t <= __w, "template argument substituting " + "__t out of bound"); + static_assert(__l <= __w, "template argument substituting " + "__l out of bound"); + static_assert(__w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bound"); static_assert(__a <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "mersenne_twister_engine template arguments out of bounds"); + "template argument substituting __a out of bound"); static_assert(__b <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "mersenne_twister_engine template arguments out of bounds"); + "template argument substituting __b out of bound"); static_assert(__c <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "mersenne_twister_engine template arguments out of bounds"); + "template argument substituting __c out of bound"); static_assert(__d <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "mersenne_twister_engine template arguments out of bounds"); + "template argument substituting __d out of bound"); static_assert(__f <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "mersenne_twister_engine template arguments out of bounds"); + "template argument substituting __f out of bound"); public: /** The type of the generated random value. */ @@ -538,13 +534,12 @@ namespace std template<typename _UIntType, size_t __w, size_t __s, size_t __r> class subtract_with_carry_engine { - __glibcxx_class_requires(_UIntType, _UnsignedIntegerConcept) - static_assert(__s > 0U && __r > __s - && __w > 0U - && __w <= static_cast<size_t> - (std::numeric_limits<_UIntType>::digits), - "template arguments out of bounds" - " in subtract_with_carry_engine"); + static_assert(std::is_unsigned<_UIntType>::value, "template argument " + "substituting _UIntType not an unsigned integral type"); + static_assert(0u < __s && __s < __r, + "template argument substituting __s out of bounds"); + static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bounds"); public: /** The type of the generated random value. */ @@ -702,9 +697,8 @@ namespace std template<typename _RandomNumberEngine, size_t __p, size_t __r> class discard_block_engine { - static_assert(__r >= 1U && __p >= __r, - "template arguments out of bounds" - " in discard_block_engine"); + static_assert(1 <= __r && __r <= __p, + "template argument substituting __r out of bounds"); public: /** The type of the generated random value. */ @@ -903,12 +897,10 @@ namespace std template<typename _RandomNumberEngine, size_t __w, typename _UIntType> class independent_bits_engine { - static_assert(__w > 0U - && __w <= - static_cast<size_t> - (std::numeric_limits<_UIntType>::digits), - "template arguments out of bounds " - "in independent_bits_engine"); + static_assert(std::is_unsigned<_UIntType>::value, "template argument " + "substituting _UIntType not an unsigned integral type"); + static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bounds"); public: /** The type of the generated random value. */ @@ -1102,9 +1094,8 @@ namespace std template<typename _RandomNumberEngine, size_t __k> class shuffle_order_engine { - static_assert(__k >= 1U, - "template arguments out of bounds" - " in shuffle_order_engine"); + static_assert(1u <= __k, "template argument substituting " + "__k out of bound"); public: /** The type of the generated random value. */ @@ -1480,7 +1471,8 @@ namespace std template<typename _IntType = int> class uniform_int_distribution { - __glibcxx_class_requires(_IntType, _IntegerConcept) + static_assert(std::is_integral<_IntType>::value, + "template argument not an integral type"); public: /** The type of the range of the distribution. */ @@ -1633,6 +1625,9 @@ namespace std template<typename _RealType = double> class uniform_real_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -1791,6 +1786,9 @@ namespace std template<typename _RealType = double> class normal_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -1943,6 +1941,9 @@ namespace std template<typename _RealType = double> class lognormal_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -2086,6 +2087,9 @@ namespace std template<typename _RealType = double> class gamma_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -2243,6 +2247,9 @@ namespace std template<typename _RealType = double> class chi_squared_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -2378,6 +2385,9 @@ namespace std template<typename _RealType = double> class cauchy_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -2519,6 +2529,9 @@ namespace std template<typename _RealType = double> class fisher_f_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -2670,6 +2683,9 @@ namespace std template<typename _RealType = double> class student_t_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -2972,7 +2988,8 @@ namespace std template<typename _IntType = int> class binomial_distribution { - __glibcxx_class_requires(_IntType, _IntegerConcept) + static_assert(std::is_integral<_IntType>::value, + "template argument not an integral type"); public: /** The type of the range of the distribution. */ @@ -3142,7 +3159,8 @@ namespace std template<typename _IntType = int> class geometric_distribution { - __glibcxx_class_requires(_IntType, _IntegerConcept) + static_assert(std::is_integral<_IntType>::value, + "template argument not an integral type"); public: /** The type of the range of the distribution. */ @@ -3287,7 +3305,8 @@ namespace std template<typename _IntType = int> class negative_binomial_distribution { - __glibcxx_class_requires(_IntType, _IntegerConcept) + static_assert(std::is_integral<_IntType>::value, + "template argument not an integral type"); public: /** The type of the range of the distribution. */ @@ -3439,7 +3458,8 @@ namespace std template<typename _IntType = int> class poisson_distribution { - __glibcxx_class_requires(_IntType, _IntegerConcept) + static_assert(std::is_integral<_IntType>::value, + "template argument not an integral type"); public: /** The type of the range of the distribution. */ @@ -3594,6 +3614,9 @@ namespace std template<typename _RealType = double> class exponential_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -3736,6 +3759,9 @@ namespace std template<typename _RealType = double> class weibull_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -3879,6 +3905,9 @@ namespace std template<typename _RealType = double> class extreme_value_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -4021,7 +4050,8 @@ namespace std template<typename _IntType = int> class discrete_distribution { - __glibcxx_class_requires(_IntType, _IntegerConcept) + static_assert(std::is_integral<_IntType>::value, + "template argument not an integral type"); public: /** The type of the range of the distribution. */ @@ -4185,6 +4215,9 @@ namespace std template<typename _RealType = double> class piecewise_constant_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; @@ -4363,6 +4396,9 @@ namespace std template<typename _RealType = double> class piecewise_linear_distribution { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + public: /** The type of the range of the distribution. */ typedef _RealType result_type; diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index 81bef585940..796df14c2c4 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -22,6 +22,8 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. +// GCC Note: Based on files from version 1.32.0 of the Boost library. + // shared_count.hpp // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. @@ -39,8 +41,6 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// GCC Note: based on version 1.32.0 of the Boost library. - /** @file bits/shared_ptr.h * This is an internal header file, included by other library headers. * You should not attempt to use it directly. @@ -53,9 +53,7 @@ # include <c++0x_warning.h> #endif -#if defined(_GLIBCXX_INCLUDE_AS_TR1) -# error C++0x header cannot be included from TR1 header -#endif +#include <bits/shared_ptr_base.h> _GLIBCXX_BEGIN_NAMESPACE(std) @@ -64,563 +62,89 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * @{ */ - // counted ptr with no deleter or allocator support - template<typename _Ptr, _Lock_policy _Lp> - class _Sp_counted_ptr - : public _Sp_counted_base<_Lp> - { - public: - _Sp_counted_ptr(_Ptr __p) - : _M_ptr(__p) { } - - virtual void - _M_dispose() // nothrow - { delete _M_ptr; } - - virtual void - _M_destroy() // nothrow - { delete this; } - - virtual void* - _M_get_deleter(const std::type_info& __ti) - { return 0; } - - _Sp_counted_ptr(const _Sp_counted_ptr&) = delete; - _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete; - - protected: - _Ptr _M_ptr; // copy constructor must not throw - }; - - // support for custom deleter and/or allocator - template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp> - class _Sp_counted_deleter - : public _Sp_counted_ptr<_Ptr, _Lp> - { - typedef typename _Alloc::template - rebind<_Sp_counted_deleter>::other _My_alloc_type; - - // Helper class that stores the Deleter and also acts as an allocator. - // Used to dispose of the owned pointer and the internal refcount - // Requires that copies of _Alloc can free each other's memory. - struct _My_Deleter - : public _My_alloc_type // copy constructor must not throw - { - _Deleter _M_del; // copy constructor must not throw - _My_Deleter(_Deleter __d, const _Alloc& __a) - : _My_alloc_type(__a), _M_del(__d) { } - }; - - protected: - typedef _Sp_counted_ptr<_Ptr, _Lp> _Base_type; - - public: - /** - * @brief - * @pre __d(__p) must not throw. - */ - _Sp_counted_deleter(_Ptr __p, _Deleter __d) - : _Base_type(__p), _M_del(__d, _Alloc()) { } - - /** - * @brief - * @pre __d(__p) must not throw. - */ - _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) - : _Base_type(__p), _M_del(__d, __a) { } - - virtual void - _M_dispose() // nothrow - { _M_del._M_del(_Base_type::_M_ptr); } - - virtual void - _M_destroy() // nothrow - { - _My_alloc_type __a(_M_del); - this->~_Sp_counted_deleter(); - __a.deallocate(this, 1); - } - - virtual void* - _M_get_deleter(const std::type_info& __ti) - { return __ti == typeid(_Deleter) ? &_M_del._M_del : 0; } - - protected: - _My_Deleter _M_del; // copy constructor must not throw - }; - - // helpers for make_shared / allocate_shared - - template<typename _Tp> - struct _Sp_destroy_inplace - { - void operator()(_Tp* __p) const { if (__p) __p->~_Tp(); } - }; - - struct _Sp_make_shared_tag { }; - - template<typename _Tp, typename _Alloc, _Lock_policy _Lp> - class _Sp_counted_ptr_inplace - : public _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp> - { - typedef _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp> - _Base_type; - - public: - _Sp_counted_ptr_inplace(_Alloc __a) - : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a) - , _M_storage() - { - void* __p = &_M_storage; - ::new (__p) _Tp(); // might throw - _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p); - } - - template<typename... _Args> - _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) - : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a) - , _M_storage() - { - void* __p = &_M_storage; - ::new (__p) _Tp(std::forward<_Args>(__args)...); // might throw - _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p); - } - - // override because the allocator needs to know the dynamic type - virtual void - _M_destroy() // nothrow - { - typedef typename _Alloc::template - rebind<_Sp_counted_ptr_inplace>::other _My_alloc_type; - _My_alloc_type __a(_Base_type::_M_del); - this->~_Sp_counted_ptr_inplace(); - __a.deallocate(this, 1); - } - - // sneaky trick so __shared_ptr can get the managed pointer - virtual void* - _M_get_deleter(const std::type_info& __ti) - { - return __ti == typeid(_Sp_make_shared_tag) - ? static_cast<void*>(&_M_storage) - : _Base_type::_M_get_deleter(__ti); - } - - private: - typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type - _M_storage; - }; - - template<_Lock_policy _Lp = __default_lock_policy> - class __weak_count; - - template<_Lock_policy _Lp = __default_lock_policy> - class __shared_count - { - public: - __shared_count() - : _M_pi(0) // nothrow - { } - - template<typename _Ptr> - __shared_count(_Ptr __p) : _M_pi(0) - { - __try - { - _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); - } - __catch(...) - { - delete __p; - __throw_exception_again; - } - } - - template<typename _Ptr, typename _Deleter> - __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0) - { - // allocator's value_type doesn't matter, will rebind it anyway - typedef std::allocator<int> _Alloc; - typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; - typedef std::allocator<_Sp_cd_type> _Alloc2; - _Alloc2 __a2; - __try - { - _M_pi = __a2.allocate(1); - ::new(static_cast<void*>(_M_pi)) _Sp_cd_type(__p, __d); - } - __catch(...) - { - __d(__p); // Call _Deleter on __p. - if (_M_pi) - __a2.deallocate(static_cast<_Sp_cd_type*>(_M_pi), 1); - __throw_exception_again; - } - } - - template<typename _Ptr, typename _Deleter, typename _Alloc> - __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0) - { - typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; - typedef typename _Alloc::template rebind<_Sp_cd_type>::other _Alloc2; - _Alloc2 __a2(__a); - __try - { - _M_pi = __a2.allocate(1); - ::new(static_cast<void*>(_M_pi)) _Sp_cd_type(__p, __d, __a); - } - __catch(...) - { - __d(__p); // Call _Deleter on __p. - if (_M_pi) - __a2.deallocate(static_cast<_Sp_cd_type*>(_M_pi), 1); - __throw_exception_again; - } - } - - template<typename _Tp, typename _Alloc, typename... _Args> - __shared_count(_Sp_make_shared_tag, _Tp*, _Alloc __a, _Args&&... __args) - : _M_pi(0) - { - typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type; - typedef typename _Alloc::template rebind<_Sp_cp_type>::other _Alloc2; - _Alloc2 __a2(__a); - __try - { - _M_pi = __a2.allocate(1); - ::new(static_cast<void*>(_M_pi)) _Sp_cp_type(__a, - std::forward<_Args>(__args)...); - } - __catch(...) - { - if (_M_pi) - __a2.deallocate(static_cast<_Sp_cp_type*>(_M_pi), 1); - __throw_exception_again; - } - } - -#if _GLIBCXX_DEPRECATED - // Special case for auto_ptr<_Tp> to provide the strong guarantee. - template<typename _Tp> - explicit - __shared_count(std::auto_ptr<_Tp>&& __r) - : _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get())) - { __r.release(); } -#endif - - // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee. - template<typename _Tp, typename _Del> - explicit - __shared_count(std::unique_ptr<_Tp, _Del>&& __r) - : _M_pi(_S_create_from_up(std::move(__r))) - { __r.release(); } - - // Throw bad_weak_ptr when __r._M_get_use_count() == 0. - explicit - __shared_count(const __weak_count<_Lp>& __r); - - ~__shared_count() // nothrow - { - if (_M_pi != 0) - _M_pi->_M_release(); - } - - __shared_count(const __shared_count& __r) - : _M_pi(__r._M_pi) // nothrow - { - if (_M_pi != 0) - _M_pi->_M_add_ref_copy(); - } - - __shared_count& - operator=(const __shared_count& __r) // nothrow - { - _Sp_counted_base<_Lp>* __tmp = __r._M_pi; - if (__tmp != _M_pi) - { - if (__tmp != 0) - __tmp->_M_add_ref_copy(); - if (_M_pi != 0) - _M_pi->_M_release(); - _M_pi = __tmp; - } - return *this; - } - - void - _M_swap(__shared_count& __r) // nothrow - { - _Sp_counted_base<_Lp>* __tmp = __r._M_pi; - __r._M_pi = _M_pi; - _M_pi = __tmp; - } - - long - _M_get_use_count() const // nothrow - { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } - - bool - _M_unique() const // nothrow - { return this->_M_get_use_count() == 1; } - - void* - _M_get_deleter(const std::type_info& __ti) const - { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; } - - bool - _M_less(const __shared_count& __rhs) const - { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } - - bool - _M_less(const __weak_count<_Lp>& __rhs) const - { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } - - // friend function injected into enclosing namespace and found by ADL - friend inline bool - operator==(const __shared_count& __a, const __shared_count& __b) - { return __a._M_pi == __b._M_pi; } - - private: - friend class __weak_count<_Lp>; - - template<typename _Tp, typename _Del> - static _Sp_counted_base<_Lp>* - _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, - typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0) - { - return new _Sp_counted_deleter<_Tp*, _Del, std::allocator<_Tp>, - _Lp>(__r.get(), __r.get_deleter()); - } - - template<typename _Tp, typename _Del> - static _Sp_counted_base<_Lp>* - _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, - typename std::enable_if<std::is_reference<_Del>::value>::type* = 0) - { - typedef typename std::remove_reference<_Del>::type _Del1; - typedef std::reference_wrapper<_Del1> _Del2; - return new _Sp_counted_deleter<_Tp*, _Del2, std::allocator<_Tp>, - _Lp>(__r.get(), std::ref(__r.get_deleter())); - } - - _Sp_counted_base<_Lp>* _M_pi; - }; - - - template<_Lock_policy _Lp> - class __weak_count - { - public: - __weak_count() - : _M_pi(0) // nothrow - { } - - __weak_count(const __shared_count<_Lp>& __r) - : _M_pi(__r._M_pi) // nothrow - { - if (_M_pi != 0) - _M_pi->_M_weak_add_ref(); - } - - __weak_count(const __weak_count<_Lp>& __r) - : _M_pi(__r._M_pi) // nothrow - { - if (_M_pi != 0) - _M_pi->_M_weak_add_ref(); - } - - ~__weak_count() // nothrow - { - if (_M_pi != 0) - _M_pi->_M_weak_release(); - } - - __weak_count<_Lp>& - operator=(const __shared_count<_Lp>& __r) // nothrow - { - _Sp_counted_base<_Lp>* __tmp = __r._M_pi; - if (__tmp != 0) - __tmp->_M_weak_add_ref(); - if (_M_pi != 0) - _M_pi->_M_weak_release(); - _M_pi = __tmp; - return *this; - } - - __weak_count<_Lp>& - operator=(const __weak_count<_Lp>& __r) // nothrow - { - _Sp_counted_base<_Lp>* __tmp = __r._M_pi; - if (__tmp != 0) - __tmp->_M_weak_add_ref(); - if (_M_pi != 0) - _M_pi->_M_weak_release(); - _M_pi = __tmp; - return *this; - } - - void - _M_swap(__weak_count<_Lp>& __r) // nothrow - { - _Sp_counted_base<_Lp>* __tmp = __r._M_pi; - __r._M_pi = _M_pi; - _M_pi = __tmp; - } - - long - _M_get_use_count() const // nothrow - { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } - - bool - _M_less(const __weak_count& __rhs) const - { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } - - bool - _M_less(const __shared_count<_Lp>& __rhs) const - { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } - - // friend function injected into enclosing namespace and found by ADL - friend inline bool - operator==(const __weak_count& __a, const __weak_count& __b) - { return __a._M_pi == __b._M_pi; } - - private: - friend class __shared_count<_Lp>; - - _Sp_counted_base<_Lp>* _M_pi; - }; - - // now that __weak_count is defined we can define this constructor: - template<_Lock_policy _Lp> - inline - __shared_count<_Lp>:: - __shared_count(const __weak_count<_Lp>& __r) - : _M_pi(__r._M_pi) + /// 2.2.3.7 shared_ptr I/O + template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp> + std::basic_ostream<_Ch, _Tr>& + operator<<(std::basic_ostream<_Ch, _Tr>& __os, + const __shared_ptr<_Tp, _Lp>& __p) { - if (_M_pi != 0) - _M_pi->_M_add_ref_lock(); - else - __throw_bad_weak_ptr(); + __os << __p.get(); + return __os; } - // Forward declarations. - template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> - class __shared_ptr; - - template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> - class __weak_ptr; - - template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> - class __enable_shared_from_this; + /// 2.2.3.10 shared_ptr get_deleter (experimental) + template<typename _Del, typename _Tp, _Lock_policy _Lp> + inline _Del* + get_deleter(const __shared_ptr<_Tp, _Lp>& __p) + { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); } - template<typename _Tp> - class shared_ptr; - - template<typename _Tp> - class weak_ptr; + /** + * @brief A smart pointer with reference-counted copy semantics. + * + * The object pointed to is deleted when the last shared_ptr pointing to + * it is destroyed or reset. + */ template<typename _Tp> - class enable_shared_from_this; - - // Support for enable_shared_from_this. - - // Friend of __enable_shared_from_this. - template<_Lock_policy _Lp, typename _Tp1, typename _Tp2> - void - __enable_shared_from_this_helper(const __shared_count<_Lp>&, - const __enable_shared_from_this<_Tp1, - _Lp>*, const _Tp2*); - - // Friend of enable_shared_from_this. - template<typename _Tp1, typename _Tp2> - void - __enable_shared_from_this_helper(const __shared_count<>&, - const enable_shared_from_this<_Tp1>*, - const _Tp2*); - - template<_Lock_policy _Lp> - inline void - __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...) - { } - - - template<typename _Tp, _Lock_policy _Lp> - class __shared_ptr + class shared_ptr : public __shared_ptr<_Tp> { public: - typedef _Tp element_type; - - /** @brief Construct an empty %__shared_ptr. + /** + * @brief Construct an empty %shared_ptr. * @post use_count()==0 && get()==0 */ - __shared_ptr() - : _M_ptr(0), _M_refcount() // never throws - { } + shared_ptr() : __shared_ptr<_Tp>() { } - /** @brief Construct a %__shared_ptr that owns the pointer @a __p. + /** + * @brief Construct a %shared_ptr that owns the pointer @a __p. * @param __p A pointer that is convertible to element_type*. * @post use_count() == 1 && get() == __p * @throw std::bad_alloc, in which case @c delete @a __p is called. */ template<typename _Tp1> - explicit - __shared_ptr(_Tp1* __p) - : _M_ptr(__p), _M_refcount(__p) - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // __glibcxx_function_requires(_CompleteConcept<_Tp1*>) - __enable_shared_from_this_helper(_M_refcount, __p, __p); - } + explicit shared_ptr(_Tp1* __p) : __shared_ptr<_Tp>(__p) { } - // - // Requirements: _Deleter's copy constructor and destructor must - // not throw - // - // __shared_ptr will release __p by calling __d(__p) - // - /** @brief Construct a %__shared_ptr that owns the pointer @a __p + /** + * @brief Construct a %shared_ptr that owns the pointer @a __p * and the deleter @a __d. * @param __p A pointer. * @param __d A deleter. * @post use_count() == 1 && get() == __p * @throw std::bad_alloc, in which case @a __d(__p) is called. + * + * Requirements: _Deleter's copy constructor and destructor must + * not throw + * + * __shared_ptr will release __p by calling __d(__p) */ - template<typename _Tp1, typename _Deleter> - __shared_ptr(_Tp1* __p, _Deleter __d) - : _M_ptr(__p), _M_refcount(__p, __d) - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // TODO requires _Deleter CopyConstructible and __d(__p) well-formed - __enable_shared_from_this_helper(_M_refcount, __p, __p); - } - - // - // Requirements: _Deleter's copy constructor and destructor must - // not throw _Alloc's copy constructor and destructor must not - // throw. - // - // __shared_ptr will release __p by calling __d(__p) - // - /** @brief Construct a %__shared_ptr that owns the pointer @a __p + template<typename _Tp1, typename _Deleter> + shared_ptr(_Tp1* __p, _Deleter __d) : __shared_ptr<_Tp>(__p, __d) { } + + /** + * @brief Construct a %shared_ptr that owns the pointer @a __p * and the deleter @a __d. * @param __p A pointer. * @param __d A deleter. * @param __a An allocator. * @post use_count() == 1 && get() == __p * @throw std::bad_alloc, in which case @a __d(__p) is called. + * + * Requirements: _Deleter's copy constructor and destructor must + * not throw _Alloc's copy constructor and destructor must not + * throw. + * + * __shared_ptr will release __p by calling __d(__p) */ template<typename _Tp1, typename _Deleter, typename _Alloc> - __shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a) - : _M_ptr(__p), _M_refcount(__p, __d, __a) - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // TODO requires _Deleter CopyConstructible and __d(__p) well-formed - __enable_shared_from_this_helper(_M_refcount, __p, __p); - } + shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a) + : __shared_ptr<_Tp>(__p, __d, __a) { } + + // Aliasing constructor - /** @brief Constructs a %__shared_ptr instance that stores @a __p + /** + * @brief Constructs a %shared_ptr instance that stores @a __p * and shares ownership with @a __r. - * @param __r A %__shared_ptr. + * @param __r A %shared_ptr. * @param __p A pointer that will remain valid while @a *__r is valid. * @post get() == __p && use_count() == __r.use_count() * @@ -634,48 +158,38 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * @endcode */ template<typename _Tp1> - __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) - : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws - { } - - // generated copy constructor, assignment, destructor are fine. - - /** @brief If @a __r is empty, constructs an empty %__shared_ptr; - * otherwise construct a %__shared_ptr that shares ownership + shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) + : __shared_ptr<_Tp>(__r, __p) { } + + /** + * @brief If @a __r is empty, constructs an empty %shared_ptr; + * otherwise construct a %shared_ptr that shares ownership * with @a __r. - * @param __r A %__shared_ptr. + * @param __r A %shared_ptr. * @post get() == __r.get() && use_count() == __r.use_count() */ template<typename _Tp1> - __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) - : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws - { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) } + shared_ptr(const shared_ptr<_Tp1>& __r) : __shared_ptr<_Tp>(__r) { } - /** @brief Move-constructs a %__shared_ptr instance from @a __r. - * @param __r A %__shared_ptr rvalue. + /** + * @brief Move-constructs a %shared_ptr instance from @a __r. + * @param __r A %shared_ptr rvalue. * @post *this contains the old value of @a __r, @a __r is empty. */ - __shared_ptr(__shared_ptr&& __r) - : _M_ptr(__r._M_ptr), _M_refcount() // never throws - { - _M_refcount._M_swap(__r._M_refcount); - __r._M_ptr = 0; - } + shared_ptr(shared_ptr&& __r) + : __shared_ptr<_Tp>(std::move(__r)) { } - /** @brief Move-constructs a %__shared_ptr instance from @a __r. - * @param __r A %__shared_ptr rvalue. + /** + * @brief Move-constructs a %shared_ptr instance from @a __r. + * @param __r A %shared_ptr rvalue. * @post *this contains the old value of @a __r, @a __r is empty. */ template<typename _Tp1> - __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) - : _M_ptr(__r._M_ptr), _M_refcount() // never throws - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - _M_refcount._M_swap(__r._M_refcount); - __r._M_ptr = 0; - } - - /** @brief Constructs a %__shared_ptr that shares ownership with @a __r + shared_ptr(shared_ptr<_Tp1>&& __r) + : __shared_ptr<_Tp>(std::move(__r)) { } + + /** + * @brief Constructs a %shared_ptr that shares ownership with @a __r * and stores a copy of the pointer stored in @a __r. * @param __r A weak_ptr. * @post use_count() == __r.use_count() @@ -683,609 +197,36 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * in which case the constructor has no effect. */ template<typename _Tp1> - explicit - __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r) - : _M_refcount(__r._M_refcount) // may throw - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // It is now safe to copy __r._M_ptr, as _M_refcount(__r._M_refcount) - // did not throw. - _M_ptr = __r._M_ptr; - } - - template<typename _Tp1, typename _Del> - explicit - __shared_ptr(const std::unique_ptr<_Tp1, _Del>&) = delete; - - /** - * If an exception is thrown this constructor has no effect. - */ - template<typename _Tp1, typename _Del> - explicit - __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) - : _M_ptr(__r.get()), _M_refcount() - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - _Tp1* __tmp = __r.get(); - _M_refcount = __shared_count<_Lp>(std::move(__r)); - __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp); - } - -#if _GLIBCXX_DEPRECATED - /** - * @post use_count() == 1 and __r.get() == 0 - */ - template<typename _Tp1> - explicit - __shared_ptr(std::auto_ptr<_Tp1>&& __r) - : _M_ptr(__r.get()), _M_refcount() - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - // TODO requires _Tp1 is complete, delete __r.release() well-formed - _Tp1* __tmp = __r.get(); - _M_refcount = __shared_count<_Lp>(std::move(__r)); - __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp); - } -#endif - - template<typename _Tp1> - __shared_ptr& - operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws - { - _M_ptr = __r._M_ptr; - _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw - return *this; - } - -#if _GLIBCXX_DEPRECATED - template<typename _Tp1> - __shared_ptr& - operator=(std::auto_ptr<_Tp1>&& __r) - { - __shared_ptr(std::move(__r)).swap(*this); - return *this; - } -#endif - - __shared_ptr& - operator=(__shared_ptr&& __r) - { - __shared_ptr(std::move(__r)).swap(*this); - return *this; - } - - template<class _Tp1> - __shared_ptr& - operator=(__shared_ptr<_Tp1, _Lp>&& __r) - { - __shared_ptr(std::move(__r)).swap(*this); - return *this; - } - - template<typename _Tp1, typename _Del> - __shared_ptr& - operator=(const std::unique_ptr<_Tp1, _Del>& __r) = delete; - - template<typename _Tp1, typename _Del> - __shared_ptr& - operator=(std::unique_ptr<_Tp1, _Del>&& __r) - { - __shared_ptr(std::move(__r)).swap(*this); - return *this; - } - - void - reset() // never throws - { __shared_ptr().swap(*this); } - - template<typename _Tp1> - void - reset(_Tp1* __p) // _Tp1 must be complete. - { - // Catch self-reset errors. - _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr); - __shared_ptr(__p).swap(*this); - } - - template<typename _Tp1, typename _Deleter> - void - reset(_Tp1* __p, _Deleter __d) - { __shared_ptr(__p, __d).swap(*this); } - - template<typename _Tp1, typename _Deleter, typename _Alloc> - void - reset(_Tp1* __p, _Deleter __d, const _Alloc& __a) - { __shared_ptr(__p, __d, __a).swap(*this); } - - // Allow class instantiation when _Tp is [cv-qual] void. - typename std::add_lvalue_reference<_Tp>::type - operator*() const // never throws - { - _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); - return *_M_ptr; - } - - _Tp* - operator->() const // never throws - { - _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); - return _M_ptr; - } - - _Tp* - get() const // never throws - { return _M_ptr; } - - explicit operator bool() const // never throws - { return _M_ptr == 0 ? false : true; } - - bool - unique() const // never throws - { return _M_refcount._M_unique(); } - - long - use_count() const // never throws - { return _M_refcount._M_get_use_count(); } - - void - swap(__shared_ptr<_Tp, _Lp>& __other) // never throws - { - std::swap(_M_ptr, __other._M_ptr); - _M_refcount._M_swap(__other._M_refcount); - } - - template<typename _Tp1> - bool - owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const - { return _M_refcount._M_less(__rhs._M_refcount); } - - template<typename _Tp1> - bool - owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const - { return _M_refcount._M_less(__rhs._M_refcount); } - - protected: - // This constructor is non-standard, it is used by allocate_shared. - template<typename _Alloc, typename... _Args> - __shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args) - : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a, - std::forward<_Args>(__args)...) - { - // _M_ptr needs to point to the newly constructed object. - // This relies on _Sp_counted_ptr_inplace::_M_get_deleter. - void* __p = _M_refcount._M_get_deleter(typeid(__tag)); - _M_ptr = static_cast<_Tp*>(__p); - __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr); - } - - template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc, - typename... _Args> - friend __shared_ptr<_Tp1, _Lp1> - __allocate_shared(_Alloc __a, _Args&&... __args); - - private: - void* - _M_get_deleter(const std::type_info& __ti) const - { return _M_refcount._M_get_deleter(__ti); } - - template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; - template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; - - template<typename _Del, typename _Tp1, _Lock_policy _Lp1> - friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&); - - _Tp* _M_ptr; // Contained pointer. - __shared_count<_Lp> _M_refcount; // Reference counter. - }; - - // 20.8.13.2.7 shared_ptr comparisons - template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> - inline bool - operator==(const __shared_ptr<_Tp1, _Lp>& __a, - const __shared_ptr<_Tp2, _Lp>& __b) - { return __a.get() == __b.get(); } - - template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> - inline bool - operator!=(const __shared_ptr<_Tp1, _Lp>& __a, - const __shared_ptr<_Tp2, _Lp>& __b) - { return __a.get() != __b.get(); } - - template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> - inline bool - operator<(const __shared_ptr<_Tp1, _Lp>& __a, - const __shared_ptr<_Tp2, _Lp>& __b) - { return __a.get() < __b.get(); } - - template<typename _Sp> - struct _Sp_less : public binary_function<_Sp, _Sp, bool> - { - bool - operator()(const _Sp& __lhs, const _Sp& __rhs) const - { - return std::less<typename _Sp::element_type*>()(__lhs.get(), - __rhs.get()); - } - }; - - template<typename _Tp, _Lock_policy _Lp> - struct less<__shared_ptr<_Tp, _Lp>> - : public _Sp_less<__shared_ptr<_Tp, _Lp>> - { }; - - // XXX LessThanComparable<_Tp> concept should provide >, >= and <= - template<typename _Tp, _Lock_policy _Lp> - inline bool - operator>(const __shared_ptr<_Tp, _Lp>& __a, - const __shared_ptr<_Tp, _Lp>& __b) - { return __a.get() > __b.get(); } - - template<typename _Tp, _Lock_policy _Lp> - inline bool - operator>=(const __shared_ptr<_Tp, _Lp>& __a, - const __shared_ptr<_Tp, _Lp>& __b) - { return __a.get() >= __b.get(); } - - template<typename _Tp, _Lock_policy _Lp> - inline bool - operator<=(const __shared_ptr<_Tp, _Lp>& __a, - const __shared_ptr<_Tp, _Lp>& __b) - { return __a.get() <= __b.get(); } - - // 2.2.3.8 shared_ptr specialized algorithms. - template<typename _Tp, _Lock_policy _Lp> - inline void - swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) - { __a.swap(__b); } - - // 2.2.3.9 shared_ptr casts - /** @warning The seemingly equivalent - * <code>shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))</code> - * will eventually result in undefined behaviour, - * attempting to delete the same object twice. - */ - template<typename _Tp, typename _Tp1, _Lock_policy _Lp> - inline __shared_ptr<_Tp, _Lp> - static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) - { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); } - - /** @warning The seemingly equivalent - * <code>shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))</code> - * will eventually result in undefined behaviour, - * attempting to delete the same object twice. - */ - template<typename _Tp, typename _Tp1, _Lock_policy _Lp> - inline __shared_ptr<_Tp, _Lp> - const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) - { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); } - - /** @warning The seemingly equivalent - * <code>shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))</code> - * will eventually result in undefined behaviour, - * attempting to delete the same object twice. - */ - template<typename _Tp, typename _Tp1, _Lock_policy _Lp> - inline __shared_ptr<_Tp, _Lp> - dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) - { - if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) - return __shared_ptr<_Tp, _Lp>(__r, __p); - return __shared_ptr<_Tp, _Lp>(); - } - - // 2.2.3.7 shared_ptr I/O - template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp> - std::basic_ostream<_Ch, _Tr>& - operator<<(std::basic_ostream<_Ch, _Tr>& __os, - const __shared_ptr<_Tp, _Lp>& __p) - { - __os << __p.get(); - return __os; - } - - // 2.2.3.10 shared_ptr get_deleter (experimental) - template<typename _Del, typename _Tp, _Lock_policy _Lp> - inline _Del* - get_deleter(const __shared_ptr<_Tp, _Lp>& __p) - { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); } - - - template<typename _Tp, _Lock_policy _Lp> - class __weak_ptr - { - public: - typedef _Tp element_type; - - __weak_ptr() - : _M_ptr(0), _M_refcount() // never throws - { } - - // Generated copy constructor, assignment, destructor are fine. - - // The "obvious" converting constructor implementation: - // - // template<typename _Tp1> - // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) - // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws - // { } - // - // has a serious problem. - // - // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr) - // conversion may require access to *__r._M_ptr (virtual inheritance). - // - // It is not possible to avoid spurious access violations since - // in multithreaded programs __r._M_ptr may be invalidated at any point. - template<typename _Tp1> - __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) - : _M_refcount(__r._M_refcount) // never throws - { - __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - _M_ptr = __r.lock().get(); - } - - template<typename _Tp1> - __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) - : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws - { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) } - - template<typename _Tp1> - __weak_ptr& - operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws - { - _M_ptr = __r.lock().get(); - _M_refcount = __r._M_refcount; - return *this; - } - - template<typename _Tp1> - __weak_ptr& - operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws - { - _M_ptr = __r._M_ptr; - _M_refcount = __r._M_refcount; - return *this; - } - - __shared_ptr<_Tp, _Lp> - lock() const // never throws - { -#ifdef __GTHREADS - // Optimization: avoid throw overhead. - if (expired()) - return __shared_ptr<element_type, _Lp>(); - - __try - { - return __shared_ptr<element_type, _Lp>(*this); - } - __catch(const bad_weak_ptr&) - { - // Q: How can we get here? - // A: Another thread may have invalidated r after the - // use_count test above. - return __shared_ptr<element_type, _Lp>(); - } - -#else - // Optimization: avoid try/catch overhead when single threaded. - return expired() ? __shared_ptr<element_type, _Lp>() - : __shared_ptr<element_type, _Lp>(*this); - -#endif - } // XXX MT - - long - use_count() const // never throws - { return _M_refcount._M_get_use_count(); } - - bool - expired() const // never throws - { return _M_refcount._M_get_use_count() == 0; } - - template<typename _Tp1> - bool - owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const - { return _M_refcount._M_less(__rhs._M_refcount); } - - template<typename _Tp1> - bool - owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const - { return _M_refcount._M_less(__rhs._M_refcount); } - - void - reset() // never throws - { __weak_ptr().swap(*this); } - - void - swap(__weak_ptr& __s) // never throws - { - std::swap(_M_ptr, __s._M_ptr); - _M_refcount._M_swap(__s._M_refcount); - } - - // comparisons - template<typename _Tp1> - bool operator<(const __weak_ptr<_Tp1, _Lp>&) const = delete; - template<typename _Tp1> - bool operator<=(const __weak_ptr<_Tp1, _Lp>&) const = delete; - template<typename _Tp1> - bool operator>(const __weak_ptr<_Tp1, _Lp>&) const = delete; - template<typename _Tp1> - bool operator>=(const __weak_ptr<_Tp1, _Lp>&) const = delete; - - private: - // Used by __enable_shared_from_this. - void - _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) - { - _M_ptr = __ptr; - _M_refcount = __refcount; - } - - template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; - template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; - friend class __enable_shared_from_this<_Tp, _Lp>; - friend class enable_shared_from_this<_Tp>; - - _Tp* _M_ptr; // Contained pointer. - __weak_count<_Lp> _M_refcount; // Reference counter. - }; - - // 20.8.13.3.7 weak_ptr specialized algorithms. - template<typename _Tp, _Lock_policy _Lp> - inline void - swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) - { __a.swap(__b); } - - /// owner_less - template<typename _Tp> struct owner_less; - - template<typename _Tp, typename _Tp1> - struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool> - { - bool - operator()(const _Tp& __lhs, const _Tp& __rhs) const - { return __lhs.owner_before(__rhs); } - bool - operator()(const _Tp& __lhs, const _Tp1& __rhs) const - { return __lhs.owner_before(__rhs); } - bool - operator()(const _Tp1& __lhs, const _Tp& __rhs) const - { return __lhs.owner_before(__rhs); } - }; - - template<typename _Tp, _Lock_policy _Lp> - struct owner_less<__shared_ptr<_Tp, _Lp>> - : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>> - { }; - - template<typename _Tp, _Lock_policy _Lp> - struct owner_less<__weak_ptr<_Tp, _Lp>> - : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>> - { - }; - - - template<typename _Tp, _Lock_policy _Lp> - class __enable_shared_from_this - { - protected: - __enable_shared_from_this() { } - - __enable_shared_from_this(const __enable_shared_from_this&) { } - - __enable_shared_from_this& - operator=(const __enable_shared_from_this&) - { return *this; } - - ~__enable_shared_from_this() { } - - public: - __shared_ptr<_Tp, _Lp> - shared_from_this() - { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); } - - __shared_ptr<const _Tp, _Lp> - shared_from_this() const - { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); } - - private: - template<typename _Tp1> - void - _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const - { _M_weak_this._M_assign(__p, __n); } - - template<typename _Tp1> - friend void - __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn, - const __enable_shared_from_this* __pe, - const _Tp1* __px) - { - if (__pe != 0) - __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); - } - - mutable __weak_ptr<_Tp, _Lp> _M_weak_this; - }; - - /** - * @brief A smart pointer with reference-counted copy semantics. - * - * The object pointed to is deleted when the last shared_ptr pointing to - * it is destroyed or reset. - */ - template<typename _Tp> - class shared_ptr - : public __shared_ptr<_Tp> - { - public: - shared_ptr() - : __shared_ptr<_Tp>() { } - - template<typename _Tp1> - explicit - shared_ptr(_Tp1* __p) - : __shared_ptr<_Tp>(__p) { } - - template<typename _Tp1, typename _Deleter> - shared_ptr(_Tp1* __p, _Deleter __d) - : __shared_ptr<_Tp>(__p, __d) { } - - template<typename _Tp1, typename _Deleter, typename _Alloc> - shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a) - : __shared_ptr<_Tp>(__p, __d, __a) { } - - // Aliasing constructor - template<typename _Tp1> - shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) - : __shared_ptr<_Tp>(__r, __p) { } - - template<typename _Tp1> - shared_ptr(const shared_ptr<_Tp1>& __r) - : __shared_ptr<_Tp>(__r) { } - - shared_ptr(shared_ptr&& __r) - : __shared_ptr<_Tp>(std::move(__r)) { } - - template<typename _Tp1> - shared_ptr(shared_ptr<_Tp1>&& __r) - : __shared_ptr<_Tp>(std::move(__r)) { } - - template<typename _Tp1> - explicit - shared_ptr(const weak_ptr<_Tp1>& __r) + explicit shared_ptr(const weak_ptr<_Tp1>& __r) : __shared_ptr<_Tp>(__r) { } #if _GLIBCXX_DEPRECATED template<typename _Tp1> - explicit - shared_ptr(std::auto_ptr<_Tp1>&& __r) + explicit + shared_ptr(std::auto_ptr<_Tp1>&& __r) : __shared_ptr<_Tp>(std::move(__r)) { } #endif template<typename _Tp1, typename _Del> - explicit - shared_ptr(const std::unique_ptr<_Tp1, _Del>&) = delete; + explicit shared_ptr(const std::unique_ptr<_Tp1, _Del>&) = delete; template<typename _Tp1, typename _Del> - explicit - shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) + explicit shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) : __shared_ptr<_Tp>(std::move(__r)) { } template<typename _Tp1> - shared_ptr& - operator=(const shared_ptr<_Tp1>& __r) // never throws - { + shared_ptr& + operator=(const shared_ptr<_Tp1>& __r) // never throws + { this->__shared_ptr<_Tp>::operator=(__r); return *this; } #if _GLIBCXX_DEPRECATED template<typename _Tp1> - shared_ptr& - operator=(std::auto_ptr<_Tp1>&& __r) - { + shared_ptr& + operator=(std::auto_ptr<_Tp1>&& __r) + { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; } @@ -1294,26 +235,26 @@ _GLIBCXX_BEGIN_NAMESPACE(std) shared_ptr& operator=(shared_ptr&& __r) { - this->__shared_ptr<_Tp>::operator=(std::move(__r)); - return *this; + this->__shared_ptr<_Tp>::operator=(std::move(__r)); + return *this; } - + template<class _Tp1> - shared_ptr& - operator=(shared_ptr<_Tp1>&& __r) - { - this->__shared_ptr<_Tp>::operator=(std::move(__r)); - return *this; - } + shared_ptr& + operator=(shared_ptr<_Tp1>&& __r) + { + this->__shared_ptr<_Tp>::operator=(std::move(__r)); + return *this; + } template<typename _Tp1, typename _Del> - shared_ptr& - operator=(const std::unique_ptr<_Tp1, _Del>& __r) = delete; + shared_ptr& + operator=(const std::unique_ptr<_Tp1, _Del>& __r) = delete; template<typename _Tp1, typename _Del> - shared_ptr& - operator=(std::unique_ptr<_Tp1, _Del>&& __r) - { + shared_ptr& + operator=(std::unique_ptr<_Tp1, _Del>&& __r) + { this->__shared_ptr<_Tp>::operator=(std::move(__r)); return *this; } @@ -1321,13 +262,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) private: // This constructor is non-standard, it is used by allocate_shared. template<typename _Alloc, typename... _Args> - shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args) - : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...) - { } + shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args) + : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...) + { } template<typename _Tp1, typename _Alloc, typename... _Args> - friend shared_ptr<_Tp1> - allocate_shared(_Alloc __a, _Args&&... __args); + friend shared_ptr<_Tp1> + allocate_shared(_Alloc __a, _Args&&... __args); }; // 20.8.13.2.7 shared_ptr comparisons @@ -1347,8 +288,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { return __a.get() < __b.get(); } template<typename _Tp> - struct less<shared_ptr<_Tp>> - : public _Sp_less<shared_ptr<_Tp>> + struct less<shared_ptr<_Tp>> : public _Sp_less<shared_ptr<_Tp>> { }; // 20.8.13.2.9 shared_ptr specialized algorithms. @@ -1373,44 +313,42 @@ _GLIBCXX_BEGIN_NAMESPACE(std) dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) { if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) - return shared_ptr<_Tp>(__r, __p); + return shared_ptr<_Tp>(__r, __p); return shared_ptr<_Tp>(); } - /** - * @brief A smart pointer with weak semantics. - * + /** + * @brief A smart pointer with weak semantics. + * * With forwarding constructors and assignment operators. */ template<typename _Tp> - class weak_ptr - : public __weak_ptr<_Tp> + class weak_ptr : public __weak_ptr<_Tp> { public: - weak_ptr() - : __weak_ptr<_Tp>() { } - + weak_ptr() : __weak_ptr<_Tp>() { } + template<typename _Tp1> - weak_ptr(const weak_ptr<_Tp1>& __r) + weak_ptr(const weak_ptr<_Tp1>& __r) : __weak_ptr<_Tp>(__r) { } template<typename _Tp1> - weak_ptr(const shared_ptr<_Tp1>& __r) + weak_ptr(const shared_ptr<_Tp1>& __r) : __weak_ptr<_Tp>(__r) { } template<typename _Tp1> - weak_ptr& - operator=(const weak_ptr<_Tp1>& __r) // never throws - { + weak_ptr& + operator=(const weak_ptr<_Tp1>& __r) // never throws + { this->__weak_ptr<_Tp>::operator=(__r); return *this; } template<typename _Tp1> - weak_ptr& - operator=(const shared_ptr<_Tp1>& __r) // never throws - { + weak_ptr& + operator=(const shared_ptr<_Tp1>& __r) // never throws + { this->__weak_ptr<_Tp>::operator=(__r); return *this; } @@ -1431,20 +369,19 @@ _GLIBCXX_BEGIN_NAMESPACE(std) return shared_ptr<_Tp>(); } #else - return this->expired() ? shared_ptr<_Tp>() - : shared_ptr<_Tp>(*this); + return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this); #endif } - // comparisons + // Comparisons template<typename _Tp1> - bool operator<(const weak_ptr<_Tp1>&) const = delete; + bool operator<(const weak_ptr<_Tp1>&) const = delete; template<typename _Tp1> - bool operator<=(const weak_ptr<_Tp1>&) const = delete; + bool operator<=(const weak_ptr<_Tp1>&) const = delete; template<typename _Tp1> - bool operator>(const weak_ptr<_Tp1>&) const = delete; + bool operator>(const weak_ptr<_Tp1>&) const = delete; template<typename _Tp1> - bool operator>=(const weak_ptr<_Tp1>&) const = delete; + bool operator>=(const weak_ptr<_Tp1>&) const = delete; }; // 20.8.13.3.7 weak_ptr specialized algorithms. @@ -1453,18 +390,24 @@ _GLIBCXX_BEGIN_NAMESPACE(std) swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) { __a.swap(__b); } - /// owner_less + + /// Primary template owner_less + template<typename _Tp> + struct owner_less; + + /// Partial specialization of owner_less for shared_ptr. template<typename _Tp> struct owner_less<shared_ptr<_Tp>> : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>> { }; + /// Partial specialization of owner_less for weak_ptr. template<typename _Tp> struct owner_less<weak_ptr<_Tp>> : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>> { }; - /** + /** * @brief Base class allowing use of member function shared_from_this. */ template<typename _Tp> @@ -1472,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { protected: enable_shared_from_this() { } - + enable_shared_from_this(const enable_shared_from_this&) { } enable_shared_from_this& @@ -1492,16 +435,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std) private: template<typename _Tp1> - void - _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const - { _M_weak_this._M_assign(__p, __n); } + void + _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const + { _M_weak_this._M_assign(__p, __n); } template<typename _Tp1> - friend void - __enable_shared_from_this_helper(const __shared_count<>& __pn, + friend void + __enable_shared_from_this_helper(const __shared_count<>& __pn, const enable_shared_from_this* __pe, const _Tp1* __px) - { + { if (__pe != 0) __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); } @@ -1509,24 +452,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) mutable weak_ptr<_Tp> _M_weak_this; }; - template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args> - inline __shared_ptr<_Tp, _Lp> - __allocate_shared(_Alloc __a, _Args&&... __args) - { - return __shared_ptr<_Tp, _Lp>(_Sp_make_shared_tag(), - std::forward<_Alloc>(__a), std::forward<_Args>(__args)...); - } - - template<typename _Tp, _Lock_policy _Lp, typename... _Args> - inline __shared_ptr<_Tp, _Lp> - __make_shared(_Args&&... __args) - { - typedef typename std::remove_const<_Tp>::type _Tp_nc; - return __allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(), - std::forward<_Args>(__args)...); - } - - /** @brief Create an object that is owned by a shared_ptr. + /** + * @brief Create an object that is owned by a shared_ptr. * @param __a An allocator. * @param __args Arguments for the @a _Tp object's constructor. * @return A shared_ptr that owns the newly created object. @@ -1541,10 +468,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) allocate_shared(_Alloc __a, _Args&&... __args) { return shared_ptr<_Tp>(_Sp_make_shared_tag(), std::forward<_Alloc>(__a), - std::forward<_Args>(__args)...); + std::forward<_Args>(__args)...); } - /** @brief Create an object that is owned by a shared_ptr. + /** + * @brief Create an object that is owned by a shared_ptr. * @param __args Arguments for the @a _Tp object's constructor. * @return A shared_ptr that owns the newly created object. * @throw std::bad_alloc, or an exception thrown from the @@ -1556,7 +484,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { typedef typename std::remove_const<_Tp>::type _Tp_nc; return allocate_shared<_Tp>(std::allocator<_Tp_nc>(), - std::forward<_Args>(__args)...); + std::forward<_Args>(__args)...); } // @} group pointer_abstractions diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h new file mode 100644 index 00000000000..b8083e405c8 --- /dev/null +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -0,0 +1,1114 @@ +// shared_ptr and weak_ptr implementation details -*- C++ -*- + +// Copyright (C) 2007, 2008, 2009 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/>. + +// GCC Note: Based on files from version 1.32.0 of the Boost library. + +// shared_count.hpp +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. + +// shared_ptr.hpp +// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes. +// Copyright (C) 2001, 2002, 2003 Peter Dimov + +// weak_ptr.hpp +// Copyright (C) 2001, 2002, 2003 Peter Dimov + +// enable_shared_from_this.hpp +// Copyright (C) 2002 Peter Dimov + +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +/** @file bits/shared_ptr_base.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +#ifndef _SHARED_PTR_BASE_H +#define _SHARED_PTR_BASE_H 1 + +_GLIBCXX_BEGIN_NAMESPACE(std) + + // Forward declarations. + template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> + class __shared_ptr; + + template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> + class __weak_ptr; + + template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> + class __enable_shared_from_this; + + template<typename _Tp> + class shared_ptr; + + template<typename _Tp> + class weak_ptr; + + template<typename _Tp> + struct owner_less; + + template<typename _Tp> + class enable_shared_from_this; + + template<_Lock_policy _Lp = __default_lock_policy> + class __weak_count; + + template<_Lock_policy _Lp = __default_lock_policy> + class __shared_count; + + + // Counted ptr with no deleter or allocator support + template<typename _Ptr, _Lock_policy _Lp> + class _Sp_counted_ptr : public _Sp_counted_base<_Lp> + { + public: + _Sp_counted_ptr(_Ptr __p) + : _M_ptr(__p) { } + + virtual void + _M_dispose() // nothrow + { delete _M_ptr; } + + virtual void + _M_destroy() // nothrow + { delete this; } + + virtual void* + _M_get_deleter(const std::type_info& __ti) + { return 0; } + + _Sp_counted_ptr(const _Sp_counted_ptr&) = delete; + _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete; + + protected: + _Ptr _M_ptr; // copy constructor must not throw + }; + + // Support for custom deleter and/or allocator + template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp> + class _Sp_counted_deleter : public _Sp_counted_ptr<_Ptr, _Lp> + { + typedef typename _Alloc::template + rebind<_Sp_counted_deleter>::other _My_alloc_type; + + // Helper class that stores the Deleter and also acts as an allocator. + // Used to dispose of the owned pointer and the internal refcount + // Requires that copies of _Alloc can free each other's memory. + struct _My_Deleter + : public _My_alloc_type // copy constructor must not throw + { + _Deleter _M_del; // copy constructor must not throw + _My_Deleter(_Deleter __d, const _Alloc& __a) + : _My_alloc_type(__a), _M_del(__d) { } + }; + + protected: + typedef _Sp_counted_ptr<_Ptr, _Lp> _Base_type; + + public: + // __d(__p) must not throw. + _Sp_counted_deleter(_Ptr __p, _Deleter __d) + : _Base_type(__p), _M_del(__d, _Alloc()) { } + + // __d(__p) must not throw. + _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) + : _Base_type(__p), _M_del(__d, __a) { } + + virtual void + _M_dispose() // nothrow + { _M_del._M_del(_Base_type::_M_ptr); } + + virtual void + _M_destroy() // nothrow + { + _My_alloc_type __a(_M_del); + this->~_Sp_counted_deleter(); + __a.deallocate(this, 1); + } + + virtual void* + _M_get_deleter(const std::type_info& __ti) + { return __ti == typeid(_Deleter) ? &_M_del._M_del : 0; } + + protected: + _My_Deleter _M_del; // copy constructor must not throw + }; + + // helpers for make_shared / allocate_shared + + template<typename _Tp> + struct _Sp_destroy_inplace + { + void operator()(_Tp* __p) const { if (__p) __p->~_Tp(); } + }; + + struct _Sp_make_shared_tag { }; + + template<typename _Tp, typename _Alloc, _Lock_policy _Lp> + class _Sp_counted_ptr_inplace + : public _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp> + { + typedef _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp> + _Base_type; + + public: + _Sp_counted_ptr_inplace(_Alloc __a) + : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a) + , _M_storage() + { + void* __p = &_M_storage; + ::new (__p) _Tp(); // might throw + _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p); + } + + template<typename... _Args> + _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) + : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a) + , _M_storage() + { + void* __p = &_M_storage; + ::new (__p) _Tp(std::forward<_Args>(__args)...); // might throw + _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p); + } + + // Override because the allocator needs to know the dynamic type + virtual void + _M_destroy() // nothrow + { + typedef typename _Alloc::template + rebind<_Sp_counted_ptr_inplace>::other _My_alloc_type; + _My_alloc_type __a(_Base_type::_M_del); + this->~_Sp_counted_ptr_inplace(); + __a.deallocate(this, 1); + } + + // Sneaky trick so __shared_ptr can get the managed pointer + virtual void* + _M_get_deleter(const std::type_info& __ti) + { + return __ti == typeid(_Sp_make_shared_tag) + ? static_cast<void*>(&_M_storage) + : _Base_type::_M_get_deleter(__ti); + } + + private: + typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type + _M_storage; + }; + + template<_Lock_policy _Lp> + class __shared_count + { + public: + __shared_count() : _M_pi(0) // nothrow + { } + + template<typename _Ptr> + __shared_count(_Ptr __p) : _M_pi(0) + { + __try + { + _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); + } + __catch(...) + { + delete __p; + __throw_exception_again; + } + } + + template<typename _Ptr, typename _Deleter> + __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0) + { + // The allocator's value_type doesn't matter, will rebind it anyway. + typedef std::allocator<int> _Alloc; + typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; + typedef std::allocator<_Sp_cd_type> _Alloc2; + _Alloc2 __a2; + __try + { + _M_pi = __a2.allocate(1); + ::new(static_cast<void*>(_M_pi)) _Sp_cd_type(__p, __d); + } + __catch(...) + { + __d(__p); // Call _Deleter on __p. + if (_M_pi) + __a2.deallocate(static_cast<_Sp_cd_type*>(_M_pi), 1); + __throw_exception_again; + } + } + + template<typename _Ptr, typename _Deleter, typename _Alloc> + __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0) + { + typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; + typedef typename _Alloc::template rebind<_Sp_cd_type>::other _Alloc2; + _Alloc2 __a2(__a); + __try + { + _M_pi = __a2.allocate(1); + ::new(static_cast<void*>(_M_pi)) _Sp_cd_type(__p, __d, __a); + } + __catch(...) + { + __d(__p); // Call _Deleter on __p. + if (_M_pi) + __a2.deallocate(static_cast<_Sp_cd_type*>(_M_pi), 1); + __throw_exception_again; + } + } + + template<typename _Tp, typename _Alloc, typename... _Args> + __shared_count(_Sp_make_shared_tag, _Tp*, _Alloc __a, _Args&&... __args) + : _M_pi(0) + { + typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type; + typedef typename _Alloc::template rebind<_Sp_cp_type>::other _Alloc2; + _Alloc2 __a2(__a); + __try + { + _M_pi = __a2.allocate(1); + ::new(static_cast<void*>(_M_pi)) _Sp_cp_type(__a, + std::forward<_Args>(__args)...); + } + __catch(...) + { + if (_M_pi) + __a2.deallocate(static_cast<_Sp_cp_type*>(_M_pi), 1); + __throw_exception_again; + } + } + +#if _GLIBCXX_DEPRECATED + // Special case for auto_ptr<_Tp> to provide the strong guarantee. + template<typename _Tp> + explicit __shared_count(std::auto_ptr<_Tp>&& __r) + : _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get())) + { __r.release(); } +#endif + + // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee. + template<typename _Tp, typename _Del> + explicit __shared_count(std::unique_ptr<_Tp, _Del>&& __r) + : _M_pi(_S_create_from_up(std::move(__r))) + { __r.release(); } + + // Throw bad_weak_ptr when __r._M_get_use_count() == 0. + explicit __shared_count(const __weak_count<_Lp>& __r); + + ~__shared_count() // nothrow + { + if (_M_pi != 0) + _M_pi->_M_release(); + } + + __shared_count(const __shared_count& __r) + : _M_pi(__r._M_pi) // nothrow + { + if (_M_pi != 0) + _M_pi->_M_add_ref_copy(); + } + + __shared_count& + operator=(const __shared_count& __r) // nothrow + { + _Sp_counted_base<_Lp>* __tmp = __r._M_pi; + if (__tmp != _M_pi) + { + if (__tmp != 0) + __tmp->_M_add_ref_copy(); + if (_M_pi != 0) + _M_pi->_M_release(); + _M_pi = __tmp; + } + return *this; + } + + void + _M_swap(__shared_count& __r) // nothrow + { + _Sp_counted_base<_Lp>* __tmp = __r._M_pi; + __r._M_pi = _M_pi; + _M_pi = __tmp; + } + + long + _M_get_use_count() const // nothrow + { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } + + bool + _M_unique() const // nothrow + { return this->_M_get_use_count() == 1; } + + void* + _M_get_deleter(const std::type_info& __ti) const + { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; } + + bool + _M_less(const __shared_count& __rhs) const + { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } + + bool + _M_less(const __weak_count<_Lp>& __rhs) const + { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } + + // Friend function injected into enclosing namespace and found by ADL + friend inline bool + operator==(const __shared_count& __a, const __shared_count& __b) + { return __a._M_pi == __b._M_pi; } + + private: + friend class __weak_count<_Lp>; + + template<typename _Tp, typename _Del> + static _Sp_counted_base<_Lp>* + _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, + typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0) + { + return new _Sp_counted_deleter<_Tp*, _Del, std::allocator<_Tp>, + _Lp>(__r.get(), __r.get_deleter()); + } + + template<typename _Tp, typename _Del> + static _Sp_counted_base<_Lp>* + _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, + typename std::enable_if<std::is_reference<_Del>::value>::type* = 0) + { + typedef typename std::remove_reference<_Del>::type _Del1; + typedef std::reference_wrapper<_Del1> _Del2; + return new _Sp_counted_deleter<_Tp*, _Del2, std::allocator<_Tp>, + _Lp>(__r.get(), std::ref(__r.get_deleter())); + } + + _Sp_counted_base<_Lp>* _M_pi; + }; + + + template<_Lock_policy _Lp> + class __weak_count + { + public: + __weak_count() : _M_pi(0) // nothrow + { } + + __weak_count(const __shared_count<_Lp>& __r) : _M_pi(__r._M_pi) // nothrow + { + if (_M_pi != 0) + _M_pi->_M_weak_add_ref(); + } + + __weak_count(const __weak_count<_Lp>& __r) : _M_pi(__r._M_pi) // nothrow + { + if (_M_pi != 0) + _M_pi->_M_weak_add_ref(); + } + + ~__weak_count() // nothrow + { + if (_M_pi != 0) + _M_pi->_M_weak_release(); + } + + __weak_count<_Lp>& + operator=(const __shared_count<_Lp>& __r) // nothrow + { + _Sp_counted_base<_Lp>* __tmp = __r._M_pi; + if (__tmp != 0) + __tmp->_M_weak_add_ref(); + if (_M_pi != 0) + _M_pi->_M_weak_release(); + _M_pi = __tmp; + return *this; + } + + __weak_count<_Lp>& + operator=(const __weak_count<_Lp>& __r) // nothrow + { + _Sp_counted_base<_Lp>* __tmp = __r._M_pi; + if (__tmp != 0) + __tmp->_M_weak_add_ref(); + if (_M_pi != 0) + _M_pi->_M_weak_release(); + _M_pi = __tmp; + return *this; + } + + void + _M_swap(__weak_count<_Lp>& __r) // nothrow + { + _Sp_counted_base<_Lp>* __tmp = __r._M_pi; + __r._M_pi = _M_pi; + _M_pi = __tmp; + } + + long + _M_get_use_count() const // nothrow + { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } + + bool + _M_less(const __weak_count& __rhs) const + { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } + + bool + _M_less(const __shared_count<_Lp>& __rhs) const + { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } + + // Friend function injected into enclosing namespace and found by ADL + friend inline bool + operator==(const __weak_count& __a, const __weak_count& __b) + { return __a._M_pi == __b._M_pi; } + + private: + friend class __shared_count<_Lp>; + + _Sp_counted_base<_Lp>* _M_pi; + }; + + // Now that __weak_count is defined we can define this constructor: + template<_Lock_policy _Lp> + inline __shared_count<_Lp>:: __shared_count(const __weak_count<_Lp>& __r) + : _M_pi(__r._M_pi) + { + if (_M_pi != 0) + _M_pi->_M_add_ref_lock(); + else + __throw_bad_weak_ptr(); + } + + + // Support for enable_shared_from_this. + + // Friend of __enable_shared_from_this. + template<_Lock_policy _Lp, typename _Tp1, typename _Tp2> + void + __enable_shared_from_this_helper(const __shared_count<_Lp>&, + const __enable_shared_from_this<_Tp1, + _Lp>*, const _Tp2*); + + // Friend of enable_shared_from_this. + template<typename _Tp1, typename _Tp2> + void + __enable_shared_from_this_helper(const __shared_count<>&, + const enable_shared_from_this<_Tp1>*, + const _Tp2*); + + template<_Lock_policy _Lp> + inline void + __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...) + { } + + + template<typename _Tp, _Lock_policy _Lp> + class __shared_ptr + { + public: + typedef _Tp element_type; + + __shared_ptr() : _M_ptr(0), _M_refcount() // never throws + { } + + template<typename _Tp1> + explicit __shared_ptr(_Tp1* __p) : _M_ptr(__p), _M_refcount(__p) + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + // __glibcxx_function_requires(_CompleteConcept<_Tp1*>) + __enable_shared_from_this_helper(_M_refcount, __p, __p); + } + + template<typename _Tp1, typename _Deleter> + __shared_ptr(_Tp1* __p, _Deleter __d) + : _M_ptr(__p), _M_refcount(__p, __d) + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + // TODO requires _Deleter CopyConstructible and __d(__p) well-formed + __enable_shared_from_this_helper(_M_refcount, __p, __p); + } + + template<typename _Tp1, typename _Deleter, typename _Alloc> + __shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a) + : _M_ptr(__p), _M_refcount(__p, __d, __a) + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + // TODO requires _Deleter CopyConstructible and __d(__p) well-formed + __enable_shared_from_this_helper(_M_refcount, __p, __p); + } + + template<typename _Tp1> + __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) + : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws + { } + + // generated copy constructor, assignment, destructor are fine. + + template<typename _Tp1> + __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) + : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws + { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) } + + __shared_ptr(__shared_ptr&& __r) + : _M_ptr(__r._M_ptr), _M_refcount() // never throws + { + _M_refcount._M_swap(__r._M_refcount); + __r._M_ptr = 0; + } + + template<typename _Tp1> + __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) + : _M_ptr(__r._M_ptr), _M_refcount() // never throws + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + _M_refcount._M_swap(__r._M_refcount); + __r._M_ptr = 0; + } + + template<typename _Tp1> + explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r) + : _M_refcount(__r._M_refcount) // may throw + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + + // It is now safe to copy __r._M_ptr, as + // _M_refcount(__r._M_refcount) did not throw. + _M_ptr = __r._M_ptr; + } + + template<typename _Tp1, typename _Del> + explicit __shared_ptr(const std::unique_ptr<_Tp1, _Del>&) = delete; + + // If an exception is thrown this constructor has no effect. + template<typename _Tp1, typename _Del> + explicit __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) + : _M_ptr(__r.get()), _M_refcount() + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + _Tp1* __tmp = __r.get(); + _M_refcount = __shared_count<_Lp>(std::move(__r)); + __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp); + } + +#if _GLIBCXX_DEPRECATED + // Postcondition: use_count() == 1 and __r.get() == 0 + template<typename _Tp1> + explicit __shared_ptr(std::auto_ptr<_Tp1>&& __r) + : _M_ptr(__r.get()), _M_refcount() + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + // TODO requires _Tp1 is complete, delete __r.release() well-formed + _Tp1* __tmp = __r.get(); + _M_refcount = __shared_count<_Lp>(std::move(__r)); + __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp); + } +#endif + + template<typename _Tp1> + __shared_ptr& + operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws + { + _M_ptr = __r._M_ptr; + _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw + return *this; + } + +#if _GLIBCXX_DEPRECATED + template<typename _Tp1> + __shared_ptr& + operator=(std::auto_ptr<_Tp1>&& __r) + { + __shared_ptr(std::move(__r)).swap(*this); + return *this; + } +#endif + + __shared_ptr& + operator=(__shared_ptr&& __r) + { + __shared_ptr(std::move(__r)).swap(*this); + return *this; + } + + template<class _Tp1> + __shared_ptr& + operator=(__shared_ptr<_Tp1, _Lp>&& __r) + { + __shared_ptr(std::move(__r)).swap(*this); + return *this; + } + + template<typename _Tp1, typename _Del> + __shared_ptr& + operator=(const std::unique_ptr<_Tp1, _Del>& __r) = delete; + + template<typename _Tp1, typename _Del> + __shared_ptr& + operator=(std::unique_ptr<_Tp1, _Del>&& __r) + { + __shared_ptr(std::move(__r)).swap(*this); + return *this; + } + + void + reset() // never throws + { __shared_ptr().swap(*this); } + + template<typename _Tp1> + void + reset(_Tp1* __p) // _Tp1 must be complete. + { + // Catch self-reset errors. + _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr); + __shared_ptr(__p).swap(*this); + } + + template<typename _Tp1, typename _Deleter> + void + reset(_Tp1* __p, _Deleter __d) + { __shared_ptr(__p, __d).swap(*this); } + + template<typename _Tp1, typename _Deleter, typename _Alloc> + void + reset(_Tp1* __p, _Deleter __d, const _Alloc& __a) + { __shared_ptr(__p, __d, __a).swap(*this); } + + // Allow class instantiation when _Tp is [cv-qual] void. + typename std::add_lvalue_reference<_Tp>::type + operator*() const // never throws + { + _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); + return *_M_ptr; + } + + _Tp* + operator->() const // never throws + { + _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); + return _M_ptr; + } + + _Tp* + get() const // never throws + { return _M_ptr; } + + explicit operator bool() const // never throws + { return _M_ptr == 0 ? false : true; } + + bool + unique() const // never throws + { return _M_refcount._M_unique(); } + + long + use_count() const // never throws + { return _M_refcount._M_get_use_count(); } + + void + swap(__shared_ptr<_Tp, _Lp>& __other) // never throws + { + std::swap(_M_ptr, __other._M_ptr); + _M_refcount._M_swap(__other._M_refcount); + } + + template<typename _Tp1> + bool + owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const + { return _M_refcount._M_less(__rhs._M_refcount); } + + template<typename _Tp1> + bool + owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const + { return _M_refcount._M_less(__rhs._M_refcount); } + + protected: + // This constructor is non-standard, it is used by allocate_shared. + template<typename _Alloc, typename... _Args> + __shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args) + : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a, + std::forward<_Args>(__args)...) + { + // _M_ptr needs to point to the newly constructed object. + // This relies on _Sp_counted_ptr_inplace::_M_get_deleter. + void* __p = _M_refcount._M_get_deleter(typeid(__tag)); + _M_ptr = static_cast<_Tp*>(__p); + __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr); + } + + template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc, + typename... _Args> + friend __shared_ptr<_Tp1, _Lp1> + __allocate_shared(_Alloc __a, _Args&&... __args); + + private: + void* + _M_get_deleter(const std::type_info& __ti) const + { return _M_refcount._M_get_deleter(__ti); } + + template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; + template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; + + template<typename _Del, typename _Tp1, _Lock_policy _Lp1> + friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&); + + _Tp* _M_ptr; // Contained pointer. + __shared_count<_Lp> _M_refcount; // Reference counter. + }; + + + // 20.8.13.2.7 shared_ptr comparisons + template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> + inline bool + operator==(const __shared_ptr<_Tp1, _Lp>& __a, + const __shared_ptr<_Tp2, _Lp>& __b) + { return __a.get() == __b.get(); } + + template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> + inline bool + operator!=(const __shared_ptr<_Tp1, _Lp>& __a, + const __shared_ptr<_Tp2, _Lp>& __b) + { return __a.get() != __b.get(); } + + template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> + inline bool + operator<(const __shared_ptr<_Tp1, _Lp>& __a, + const __shared_ptr<_Tp2, _Lp>& __b) + { return __a.get() < __b.get(); } + + template<typename _Sp> + struct _Sp_less : public binary_function<_Sp, _Sp, bool> + { + bool + operator()(const _Sp& __lhs, const _Sp& __rhs) const + { + typedef typename _Sp::element_type element_type; + return std::less<element_type*>()(__lhs.get(), __rhs.get()); + } + }; + + template<typename _Tp, _Lock_policy _Lp> + struct less<__shared_ptr<_Tp, _Lp>> + : public _Sp_less<__shared_ptr<_Tp, _Lp>> + { }; + + // XXX LessThanComparable<_Tp> concept should provide >, >= and <= + template<typename _Tp, _Lock_policy _Lp> + inline bool + operator>(const __shared_ptr<_Tp, _Lp>& __a, + const __shared_ptr<_Tp, _Lp>& __b) + { return __a.get() > __b.get(); } + + template<typename _Tp, _Lock_policy _Lp> + inline bool + operator>=(const __shared_ptr<_Tp, _Lp>& __a, + const __shared_ptr<_Tp, _Lp>& __b) + { return __a.get() >= __b.get(); } + + template<typename _Tp, _Lock_policy _Lp> + inline bool + operator<=(const __shared_ptr<_Tp, _Lp>& __a, + const __shared_ptr<_Tp, _Lp>& __b) + { return __a.get() <= __b.get(); } + + // 2.2.3.8 shared_ptr specialized algorithms. + template<typename _Tp, _Lock_policy _Lp> + inline void + swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) + { __a.swap(__b); } + + // 2.2.3.9 shared_ptr casts + + // The seemingly equivalent code: + // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get())) + // will eventually result in undefined behaviour, attempting to + // delete the same object twice. + /// static_pointer_cast + template<typename _Tp, typename _Tp1, _Lock_policy _Lp> + inline __shared_ptr<_Tp, _Lp> + static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) + { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); } + + // The seemingly equivalent code: + // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get())) + // will eventually result in undefined behaviour, attempting to + // delete the same object twice. + /// const_pointer_cast + template<typename _Tp, typename _Tp1, _Lock_policy _Lp> + inline __shared_ptr<_Tp, _Lp> + const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) + { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); } + + // The seemingly equivalent code: + // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get())) + // will eventually result in undefined behaviour, attempting to + // delete the same object twice. + /// dynamic_pointer_cast + template<typename _Tp, typename _Tp1, _Lock_policy _Lp> + inline __shared_ptr<_Tp, _Lp> + dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) + { + if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) + return __shared_ptr<_Tp, _Lp>(__r, __p); + return __shared_ptr<_Tp, _Lp>(); + } + + + template<typename _Tp, _Lock_policy _Lp> + class __weak_ptr + { + public: + typedef _Tp element_type; + + __weak_ptr() : _M_ptr(0), _M_refcount() // never throws + { } + + // Generated copy constructor, assignment, destructor are fine. + + // The "obvious" converting constructor implementation: + // + // template<typename _Tp1> + // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) + // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws + // { } + // + // has a serious problem. + // + // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr) + // conversion may require access to *__r._M_ptr (virtual inheritance). + // + // It is not possible to avoid spurious access violations since + // in multithreaded programs __r._M_ptr may be invalidated at any point. + template<typename _Tp1> + __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) + : _M_refcount(__r._M_refcount) // never throws + { + __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) + _M_ptr = __r.lock().get(); + } + + template<typename _Tp1> + __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) + : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws + { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) } + + template<typename _Tp1> + __weak_ptr& + operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws + { + _M_ptr = __r.lock().get(); + _M_refcount = __r._M_refcount; + return *this; + } + + template<typename _Tp1> + __weak_ptr& + operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws + { + _M_ptr = __r._M_ptr; + _M_refcount = __r._M_refcount; + return *this; + } + + __shared_ptr<_Tp, _Lp> + lock() const // never throws + { +#ifdef __GTHREADS + // Optimization: avoid throw overhead. + if (expired()) + return __shared_ptr<element_type, _Lp>(); + + __try + { + return __shared_ptr<element_type, _Lp>(*this); + } + __catch(const bad_weak_ptr&) + { + // Q: How can we get here? + // A: Another thread may have invalidated r after the + // use_count test above. + return __shared_ptr<element_type, _Lp>(); + } + +#else + // Optimization: avoid try/catch overhead when single threaded. + return expired() ? __shared_ptr<element_type, _Lp>() + : __shared_ptr<element_type, _Lp>(*this); + +#endif + } // XXX MT + + long + use_count() const // never throws + { return _M_refcount._M_get_use_count(); } + + bool + expired() const // never throws + { return _M_refcount._M_get_use_count() == 0; } + + template<typename _Tp1> + bool + owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const + { return _M_refcount._M_less(__rhs._M_refcount); } + + template<typename _Tp1> + bool + owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const + { return _M_refcount._M_less(__rhs._M_refcount); } + + void + reset() // never throws + { __weak_ptr().swap(*this); } + + void + swap(__weak_ptr& __s) // never throws + { + std::swap(_M_ptr, __s._M_ptr); + _M_refcount._M_swap(__s._M_refcount); + } + + // Comparisons + template<typename _Tp1> + bool operator<(const __weak_ptr<_Tp1, _Lp>&) const = delete; + + template<typename _Tp1> + bool operator<=(const __weak_ptr<_Tp1, _Lp>&) const = delete; + + template<typename _Tp1> + bool operator>(const __weak_ptr<_Tp1, _Lp>&) const = delete; + + template<typename _Tp1> + bool operator>=(const __weak_ptr<_Tp1, _Lp>&) const = delete; + + private: + // Used by __enable_shared_from_this. + void + _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) + { + _M_ptr = __ptr; + _M_refcount = __refcount; + } + + template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; + template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; + friend class __enable_shared_from_this<_Tp, _Lp>; + friend class enable_shared_from_this<_Tp>; + + _Tp* _M_ptr; // Contained pointer. + __weak_count<_Lp> _M_refcount; // Reference counter. + }; + + // 20.8.13.3.7 weak_ptr specialized algorithms. + template<typename _Tp, _Lock_policy _Lp> + inline void + swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) + { __a.swap(__b); } + + template<typename _Tp, typename _Tp1> + struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool> + { + bool + operator()(const _Tp& __lhs, const _Tp& __rhs) const + { return __lhs.owner_before(__rhs); } + + bool + operator()(const _Tp& __lhs, const _Tp1& __rhs) const + { return __lhs.owner_before(__rhs); } + + bool + operator()(const _Tp1& __lhs, const _Tp& __rhs) const + { return __lhs.owner_before(__rhs); } + }; + + template<typename _Tp, _Lock_policy _Lp> + struct owner_less<__shared_ptr<_Tp, _Lp>> + : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>> + { }; + + template<typename _Tp, _Lock_policy _Lp> + struct owner_less<__weak_ptr<_Tp, _Lp>> + : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>> + { }; + + + template<typename _Tp, _Lock_policy _Lp> + class __enable_shared_from_this + { + protected: + __enable_shared_from_this() { } + + __enable_shared_from_this(const __enable_shared_from_this&) { } + + __enable_shared_from_this& + operator=(const __enable_shared_from_this&) + { return *this; } + + ~__enable_shared_from_this() { } + + public: + __shared_ptr<_Tp, _Lp> + shared_from_this() + { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); } + + __shared_ptr<const _Tp, _Lp> + shared_from_this() const + { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); } + + private: + template<typename _Tp1> + void + _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const + { _M_weak_this._M_assign(__p, __n); } + + template<typename _Tp1> + friend void + __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn, + const __enable_shared_from_this* __pe, + const _Tp1* __px) + { + if (__pe != 0) + __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); + } + + mutable __weak_ptr<_Tp, _Lp> _M_weak_this; + }; + + + template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args> + inline __shared_ptr<_Tp, _Lp> + __allocate_shared(_Alloc __a, _Args&&... __args) + { + return __shared_ptr<_Tp, _Lp>(_Sp_make_shared_tag(), + std::forward<_Alloc>(__a), std::forward<_Args>(__args)...); + } + + template<typename _Tp, _Lock_policy _Lp, typename... _Args> + inline __shared_ptr<_Tp, _Lp> + __make_shared(_Args&&... __args) + { + typedef typename std::remove_const<_Tp>::type _Tp_nc; + return __allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(), + std::forward<_Args>(__args)...); + } + +_GLIBCXX_END_NAMESPACE + +#endif // _SHARED_PTR_BASE_H diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index a745295e9b0..9b6f2afb9ec 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -1647,53 +1647,64 @@ _GLIBCXX_BEGIN_NAMESPACE(std) typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; - const _Distance __n = __last - __first; - const _Distance __k = __middle - __first; - const _Distance __l = __n - __k; + _Distance __n = __last - __first; + _Distance __k = __middle - __first; - if (__k == __l) + if (__k == __n - __k) { std::swap_ranges(__first, __middle, __middle); return; } - const _Distance __d = std::__gcd(__n, __k); + _RandomAccessIterator __p = __first; - for (_Distance __i = 0; __i < __d; __i++) + for (;;) { - _ValueType __tmp = _GLIBCXX_MOVE(*__first); - _RandomAccessIterator __p = __first; - - if (__k < __l) + if (__k < __n - __k) { - for (_Distance __j = 0; __j < __l / __d; __j++) + if (__is_pod(_ValueType) && __k == 1) + { + _ValueType __t = _GLIBCXX_MOVE(*__p); + _GLIBCXX_MOVE3(__p + 1, __p + __n, __p); + *(__p + __n - 1) = _GLIBCXX_MOVE(__t); + return; + } + _RandomAccessIterator __q = __p + __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) { - if (__p > __first + __l) - { - *__p = _GLIBCXX_MOVE(*(__p - __l)); - __p -= __l; - } - - *__p = _GLIBCXX_MOVE(*(__p + __k)); - __p += __k; + std::iter_swap(__p, __q); + ++__p; + ++__q; } + __n %= __k; + if (__n == 0) + return; + std::swap(__n, __k); + __k = __n - __k; } else { - for (_Distance __j = 0; __j < __k / __d - 1; __j ++) + __k = __n - __k; + if (__is_pod(_ValueType) && __k == 1) { - if (__p < __last - __k) - { - *__p = _GLIBCXX_MOVE(*(__p + __k)); - __p += __k; - } - *__p = _GLIBCXX_MOVE(*(__p - __l)); - __p -= __l; + _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1)); + _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n); + *__p = _GLIBCXX_MOVE(__t); + return; } + _RandomAccessIterator __q = __p + __n; + __p = __q - __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + std::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return; + std::swap(__n, __k); } - - *__p = _GLIBCXX_MOVE(__tmp); - ++__first; } } @@ -1862,15 +1873,15 @@ _GLIBCXX_BEGIN_NAMESPACE(std) for (; __first != __last; ++__first) if (__pred(*__first)) { - *__result1 = *__first; + *__result1 = _GLIBCXX_MOVE(*__first); ++__result1; } else { - *__result2 = *__first; + *__result2 = _GLIBCXX_MOVE(*__first); ++__result2; } - std::copy(__buffer, __result2, __result1); + _GLIBCXX_MOVE3(__buffer, __result2, __result1); return __result1; } else @@ -2926,15 +2937,15 @@ _GLIBCXX_BEGIN_NAMESPACE(std) _BidirectionalIterator2 __buffer_end; if (__len1 > __len2 && __len2 <= __buffer_size) { - __buffer_end = std::copy(__middle, __last, __buffer); - std::copy_backward(__first, __middle, __last); - return std::copy(__buffer, __buffer_end, __first); + __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); + return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); } else if (__len1 <= __buffer_size) { - __buffer_end = std::copy(__first, __middle, __buffer); - std::copy(__middle, __last, __first); - return std::copy_backward(__buffer, __buffer_end, __last); + __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + _GLIBCXX_MOVE3(__middle, __last, __first); + return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); } else { @@ -2956,15 +2967,21 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { if (__len1 <= __len2 && __len1 <= __buffer_size) { - _Pointer __buffer_end = std::copy(__first, __middle, __buffer); - _GLIBCXX_STD_P::merge(__buffer, __buffer_end, __middle, __last, + _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + _GLIBCXX_STD_P::merge(_GLIBCXX_MAKE_MOVE_ITERATOR(__buffer), + _GLIBCXX_MAKE_MOVE_ITERATOR(__buffer_end), + _GLIBCXX_MAKE_MOVE_ITERATOR(__middle), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __first); } else if (__len2 <= __buffer_size) { - _Pointer __buffer_end = std::copy(__middle, __last, __buffer); - std::__merge_backward(__first, __middle, __buffer, - __buffer_end, __last); + _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + std::__merge_backward(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__middle), + _GLIBCXX_MAKE_MOVE_ITERATOR(__buffer), + _GLIBCXX_MAKE_MOVE_ITERATOR(__buffer_end), + __last); } else { @@ -3013,15 +3030,21 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { if (__len1 <= __len2 && __len1 <= __buffer_size) { - _Pointer __buffer_end = std::copy(__first, __middle, __buffer); - _GLIBCXX_STD_P::merge(__buffer, __buffer_end, __middle, __last, + _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + _GLIBCXX_STD_P::merge(_GLIBCXX_MAKE_MOVE_ITERATOR(__buffer), + _GLIBCXX_MAKE_MOVE_ITERATOR(__buffer_end), + _GLIBCXX_MAKE_MOVE_ITERATOR(__middle), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __first, __comp); } else if (__len2 <= __buffer_size) { - _Pointer __buffer_end = std::copy(__middle, __last, __buffer); - std::__merge_backward(__first, __middle, __buffer, __buffer_end, - __last, __comp); + _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + std::__merge_backward(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__middle), + _GLIBCXX_MAKE_MOVE_ITERATOR(__buffer), + _GLIBCXX_MAKE_MOVE_ITERATOR(__buffer_end), + __last,__comp); } else { @@ -3270,16 +3293,22 @@ _GLIBCXX_BEGIN_NAMESPACE(std) while (__last - __first >= __two_step) { - __result = _GLIBCXX_STD_P::merge(__first, __first + __step_size, - __first + __step_size, - __first + __two_step, - __result); + __result = _GLIBCXX_STD_P::merge( + _GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + __two_step), + __result); __first += __two_step; } __step_size = std::min(_Distance(__last - __first), __step_size); - _GLIBCXX_STD_P::merge(__first, __first + __step_size, - __first + __step_size, __last, + _GLIBCXX_STD_P::merge(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); } @@ -3295,16 +3324,23 @@ _GLIBCXX_BEGIN_NAMESPACE(std) while (__last - __first >= __two_step) { - __result = _GLIBCXX_STD_P::merge(__first, __first + __step_size, - __first + __step_size, __first + __two_step, - __result, - __comp); + __result = _GLIBCXX_STD_P::merge( + _GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + __two_step), + __result, __comp); __first += __two_step; } __step_size = std::min(_Distance(__last - __first), __step_size); - _GLIBCXX_STD_P::merge(__first, __first + __step_size, - __first + __step_size, __last, __result, __comp); + _GLIBCXX_STD_P::merge(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__first + + __step_size), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), + __result, __comp); } template<typename _RandomAccessIterator, typename _Distance> diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index c638c547887..f9c3ab2b428 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -998,7 +998,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_P) } /** - * @brief Performs "dictionary" comparison on ranges. + * @brief Performs 'dictionary' comparison on ranges. * @ingroup sorting_algorithms * @param first1 An input iterator. * @param last1 An input iterator. @@ -1006,9 +1006,9 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_P) * @param last2 An input iterator. * @return A boolean true or false. * - * "Returns true if the sequence of elements defined by the range + * 'Returns true if the sequence of elements defined by the range * [first1,last1) is lexicographically less than the sequence of elements - * defined by the range [first2,last2). Returns false otherwise." + * defined by the range [first2,last2). Returns false otherwise.' * (Quoted from [25.3.8]/1.) If the iterators are all character pointers, * then this is an inline call to @c memcmp. */ diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index eb7290053ed..a60fea60a6b 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -67,9 +67,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std) + /** + * @addtogroup iterators + * @{ + */ + // 24.4.1 Reverse iterators /** - * "Bidirectional and random access iterators have corresponding reverse + * 'Bidirectional and random access iterators have corresponding reverse * %iterator adaptors that iterate through the data structure in the * opposite direction. They have the same signatures as the corresponding * iterators. The fundamental relation between a reverse %iterator and its @@ -80,7 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * * This mapping is dictated by the fact that while there is always a * pointer past the end of an array, there might not be a valid pointer - * before the beginning of an array." [24.4.1]/1,2 + * before the beginning of an array.' [24.4.1]/1,2 * * Reverse iterators can be tricky and surprising at first. Their * semantics make sense, however, and the trickiness is a side effect of @@ -97,14 +102,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std) protected: _Iterator current; - public: - typedef _Iterator iterator_type; - typedef typename iterator_traits<_Iterator>::difference_type - difference_type; - typedef typename iterator_traits<_Iterator>::reference reference; - typedef typename iterator_traits<_Iterator>::pointer pointer; + typedef iterator_traits<_Iterator> __traits_type; public: + typedef _Iterator iterator_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::pointer pointer; + typedef typename __traits_type::reference reference; + /** * The default constructor default-initializes member @p current. * If it is a pointer, that means it is zero-initialized. @@ -651,6 +656,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) typename _Container::iterator(__i)); } + // @} group iterators + _GLIBCXX_END_NAMESPACE _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) @@ -670,15 +677,15 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) protected: _Iterator _M_current; + typedef iterator_traits<_Iterator> __traits_type; + public: - typedef _Iterator iterator_type; - typedef typename iterator_traits<_Iterator>::iterator_category - iterator_category; - typedef typename iterator_traits<_Iterator>::value_type value_type; - typedef typename iterator_traits<_Iterator>::difference_type - difference_type; - typedef typename iterator_traits<_Iterator>::reference reference; - typedef typename iterator_traits<_Iterator>::pointer pointer; + typedef _Iterator iterator_type; + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::reference reference; + typedef typename __traits_type::pointer pointer; __normal_iterator() : _M_current(_Iterator()) { } @@ -869,6 +876,11 @@ _GLIBCXX_END_NAMESPACE _GLIBCXX_BEGIN_NAMESPACE(std) + /** + * @addtogroup iterators + * @{ + */ + // 24.4.3 Move iterators /** * Class template move_iterator is an iterator adapter with the same @@ -884,18 +896,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std) protected: _Iterator _M_current; + typedef iterator_traits<_Iterator> __traits_type; + public: - typedef _Iterator iterator_type; - typedef typename iterator_traits<_Iterator>::difference_type - difference_type; + typedef _Iterator iterator_type; + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; // NB: DR 680. - typedef _Iterator pointer; - typedef typename iterator_traits<_Iterator>::value_type value_type; - typedef typename iterator_traits<_Iterator>::iterator_category - iterator_category; - typedef value_type&& reference; + typedef _Iterator pointer; + typedef value_type&& reference; - public: move_iterator() : _M_current() { } @@ -1031,6 +1042,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) make_move_iterator(const _Iterator& __i) { return move_iterator<_Iterator>(__i); } + // @} group iterators + _GLIBCXX_END_NAMESPACE #define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter) diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h index 0a854faa14c..b629ca20231 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h @@ -173,10 +173,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } #ifdef __GXX_EXPERIMENTAL_CXX0X__ - template<typename _InputIterator> - inline _InputIterator - next(_InputIterator __x, typename - iterator_traits<_InputIterator>::difference_type __n = 1) + template<typename _ForwardIterator> + inline _ForwardIterator + next(_ForwardIterator __x, typename + iterator_traits<_ForwardIterator>::difference_type __n = 1) { std::advance(__x, __n); return __x; diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h index 6dc0d7838d3..d2bf647f058 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_types.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h @@ -77,15 +77,19 @@ _GLIBCXX_BEGIN_NAMESPACE(std) //@{ /// Marking input iterators. struct input_iterator_tag { }; + /// Marking output iterators. struct output_iterator_tag { }; + /// Forward iterators support a superset of input iterator operations. struct forward_iterator_tag : public input_iterator_tag { }; + /// Bidirectional iterators support a superset of forward iterator /// operations. struct bidirectional_iterator_tag : public forward_iterator_tag { }; - /// Random-access iterators support a superset of bidirectional iterator - /// operations. + + /// Random-access iterators support a superset of bidirectional + /// iterator operations. struct random_access_iterator_tag : public bidirectional_iterator_tag { }; @@ -116,6 +120,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) }; /** + * @brief Traits class for iterators. + * * This class does nothing but define nested typedefs. The general * version simply "forwards" the nested typedefs from the Iterator * argument. Specialized versions for pointers and pointers-to-const @@ -131,6 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) typedef typename _Iterator::reference reference; }; + /// Partial specialization for pointer types. template<typename _Tp> struct iterator_traits<_Tp*> { @@ -141,6 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) typedef _Tp& reference; }; + /// Partial specialization for const pointer types. template<typename _Tp> struct iterator_traits<const _Tp*> { diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index d6c590186d6..4a9fb6be485 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -60,6 +60,10 @@ #include <bits/move.h> // for std::move / std::forward, std::decay, and // std::swap +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#include <type_traits> +#endif + _GLIBCXX_BEGIN_NAMESPACE(std) /// pair holds two objects of arbitrary type. @@ -84,7 +88,22 @@ _GLIBCXX_BEGIN_NAMESPACE(std) : first(__a), second(__b) { } #ifdef __GXX_EXPERIMENTAL_CXX0X__ - template<class _U1, class _U2> + // DR 811. + template<class _U1, class = typename + std::enable_if<std::is_convertible<_U1, _T1>::value>::type> + pair(_U1&& __x, const _T2& __y) + : first(std::forward<_U1>(__x)), + second(__y) { } + + template<class _U2, class = typename + std::enable_if<std::is_convertible<_U2, _T2>::value>::type> + pair(const _T1& __x, _U2&& __y) + : first(__x), + second(std::forward<_U2>(__y)) { } + + template<class _U1, class _U2, class = typename + std::enable_if<std::is_convertible<_U1, _T1>::value + && std::is_convertible<_U2, _T2>::value>::type> pair(_U1&& __x, _U2&& __y) : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } @@ -106,13 +125,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) : first(std::move(__p.first)), second(std::move(__p.second)) { } - // http://gcc.gnu.org/ml/libstdc++/2007-08/msg00052.html - template<class _U1, class _Arg0, class... _Args> - pair(_U1&& __x, _Arg0&& __arg0, _Args&&... __args) - : first(std::forward<_U1>(__x)), - second(std::forward<_Arg0>(__arg0), - std::forward<_Args>(__args)...) { } - pair& operator=(pair&& __p) { diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h b/libstdc++-v3/include/bits/stl_tempbuf.h index 2b887912a10..27b58bf5f81 100644 --- a/libstdc++-v3/include/bits/stl_tempbuf.h +++ b/libstdc++-v3/include/bits/stl_tempbuf.h @@ -72,9 +72,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * * This function tries to obtain storage for @c len adjacent Tp * objects. The objects themselves are not constructed, of course. - * A pair<> is returned containing "the buffer s address and + * A pair<> is returned containing 'the buffer s address and * capacity (in the units of sizeof(Tp)), or a pair of 0 values if - * no storage can be obtained." Note that the capacity obtained + * no storage can be obtained.' Note that the capacity obtained * may be less than that requested if the memory is unavailable; * you should compare len with the .second return value. * diff --git a/libstdc++-v3/include/bits/stream_iterator.h b/libstdc++-v3/include/bits/stream_iterator.h index fce6c26d1a5..90f1b552b60 100644 --- a/libstdc++-v3/include/bits/stream_iterator.h +++ b/libstdc++-v3/include/bits/stream_iterator.h @@ -36,6 +36,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) + /** + * @addtogroup iterators + * @{ + */ + /// Provides input iterator semantics for streams. template<typename _Tp, typename _CharT = char, typename _Traits = char_traits<_CharT>, typename _Dist = ptrdiff_t> @@ -206,6 +211,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { return *this; } }; + // @} group iterators + _GLIBCXX_END_NAMESPACE #endif diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index d02b555343a..71c323035a2 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -39,6 +39,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) + /** + * @addtogroup iterators + * @{ + */ + // 24.5.3 Template class istreambuf_iterator /// Provides input iterator semantics for streambufs. template<typename _CharT, typename _Traits> @@ -387,6 +392,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) return __first; } +// @} group iterators + _GLIBCXX_END_NAMESPACE #endif diff --git a/libstdc++-v3/include/bits/valarray_array.h b/libstdc++-v3/include/bits/valarray_array.h index 492891bc9d8..a12b3347b9d 100644 --- a/libstdc++-v3/include/bits/valarray_array.h +++ b/libstdc++-v3/include/bits/valarray_array.h @@ -1,7 +1,7 @@ // The template and inlines for the -*- C++ -*- internal _Array helper class. // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2007, 2009 +// 2006, 2007, 2008, 2009 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -73,7 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // Please note that this isn't exception safe. But // valarrays aren't required to be exception safe. inline static void - _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + _S_do_it(_Tp* __b, _Tp* __e) { while (__b != __e) new(__b++) _Tp(); @@ -85,13 +85,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { // For fundamental types, it suffices to say 'memset()' inline static void - _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + _S_do_it(_Tp* __b, _Tp* __e) { __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp)); } }; template<typename _Tp> inline void - __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + __valarray_default_construct(_Tp* __b, _Tp* __e) { _Array_default_ctor<_Tp, __is_scalar<_Tp>::__value>::_S_do_it(__b, __e); } @@ -105,7 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // Please note that this isn't exception safe. But // valarrays aren't required to be exception safe. inline static void - _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t) + _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) { while (__b != __e) new(__b++) _Tp(__t); @@ -116,7 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) struct _Array_init_ctor<_Tp, true> { inline static void - _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t) + _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) { while (__b != __e) *__b++ = __t; @@ -125,8 +125,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<typename _Tp> inline void - __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e, - const _Tp __t) + __valarray_fill_construct(_Tp* __b, _Tp* __e, const _Tp __t) { _Array_init_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e, __t); } @@ -141,8 +140,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // Please note that this isn't exception safe. But // valarrays aren't required to be exception safe. inline static void - _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e, - _Tp* __restrict__ __o) + _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) { while (__b != __e) new(__o++) _Tp(*__b++); @@ -153,15 +151,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std) struct _Array_copy_ctor<_Tp, true> { inline static void - _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e, - _Tp* __restrict__ __o) + _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) { __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp)); } }; template<typename _Tp> inline void - __valarray_copy_construct(const _Tp* __restrict__ __b, - const _Tp* __restrict__ __e, + __valarray_copy_construct(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) { _Array_copy_ctor<_Tp, __is_pod(_Tp)>::_S_do_it(__b, __e, __o); @@ -205,7 +201,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // Do the necessary cleanup when we're done with arrays. template<typename _Tp> inline void - __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e) + __valarray_destroy_elements(_Tp* __b, _Tp* __e) { if (!__is_pod(_Tp)) while (__b != __e) @@ -347,7 +343,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // template<typename _Tp> inline _Tp - __valarray_sum(const _Tp* __restrict__ __f, const _Tp* __restrict__ __l) + __valarray_sum(const _Tp* __f, const _Tp* __l) { _Tp __r = _Tp(); while (__f != __l) @@ -358,8 +354,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // Compute the product of all elements in range [__f, __l) template<typename _Tp> inline _Tp - __valarray_product(const _Tp* __restrict__ __f, - const _Tp* __restrict__ __l) + __valarray_product(const _Tp* __f, const _Tp* __l) { _Tp __r = _Tp(1); while (__f != __l) diff --git a/libstdc++-v3/include/c_compatibility/stdatomic.h b/libstdc++-v3/include/c_compatibility/stdatomic.h index f4771166d2b..eaa45cddac1 100644 --- a/libstdc++-v3/include/c_compatibility/stdatomic.h +++ b/libstdc++-v3/include/c_compatibility/stdatomic.h @@ -186,8 +186,11 @@ _GLIBCXX_BEGIN_EXTERN_C _GLIBCXX_END_EXTERN_C _GLIBCXX_END_NAMESPACE -// Inject into global namespace. XXX -#if defined(__cplusplus) && !defined(_GLIBCXX_STDATOMIC) +// Inject into global namespace. +#ifdef __cplusplus + +#include <cstdatomic> + using std::memory_order; using std::memory_order_relaxed; using std::memory_order_consume; diff --git a/libstdc++-v3/include/c_global/cassert b/libstdc++-v3/include/c_global/cassert index 186de0fbcd1..231e419efb5 100644 --- a/libstdc++-v3/include/c_global/cassert +++ b/libstdc++-v3/include/c_global/cassert @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file cassert - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c assert.h, diff --git a/libstdc++-v3/include/c_global/cctype b/libstdc++-v3/include/c_global/cctype index 44ef4d4a0f2..bfe45929e3c 100644 --- a/libstdc++-v3/include/c_global/cctype +++ b/libstdc++-v3/include/c_global/cctype @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cctype - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c ctype.h, diff --git a/libstdc++-v3/include/c_global/cerrno b/libstdc++-v3/include/c_global/cerrno index 371642936cf..f02d732079c 100644 --- a/libstdc++-v3/include/c_global/cerrno +++ b/libstdc++-v3/include/c_global/cerrno @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file cerrno - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c errno.h, diff --git a/libstdc++-v3/include/c_global/cfloat b/libstdc++-v3/include/c_global/cfloat index 54eb7788746..7f551446cb3 100644 --- a/libstdc++-v3/include/c_global/cfloat +++ b/libstdc++-v3/include/c_global/cfloat @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cfloat - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c float.h, diff --git a/libstdc++-v3/include/c_global/ciso646 b/libstdc++-v3/include/c_global/ciso646 index a3c3f9b7794..bb7e6294fd8 100644 --- a/libstdc++-v3/include/c_global/ciso646 +++ b/libstdc++-v3/include/c_global/ciso646 @@ -23,7 +23,7 @@ // <http://www.gnu.org/licenses/>. /** @file ciso646 - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c iso646.h, diff --git a/libstdc++-v3/include/c_global/climits b/libstdc++-v3/include/c_global/climits index 943d69e522f..1bbe6cf27a5 100644 --- a/libstdc++-v3/include/c_global/climits +++ b/libstdc++-v3/include/c_global/climits @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/climits - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c limits.h, diff --git a/libstdc++-v3/include/c_global/clocale b/libstdc++-v3/include/c_global/clocale index eb955c9b181..52d2b9d2148 100644 --- a/libstdc++-v3/include/c_global/clocale +++ b/libstdc++-v3/include/c_global/clocale @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file clocale - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c locale.h, diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath index a5c31c436d7..2568d6b3bf6 100644 --- a/libstdc++-v3/include/c_global/cmath +++ b/libstdc++-v3/include/c_global/cmath @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cmath - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c math.h, diff --git a/libstdc++-v3/include/c_global/csetjmp b/libstdc++-v3/include/c_global/csetjmp index 6d7ecab47b6..c643d1b437a 100644 --- a/libstdc++-v3/include/c_global/csetjmp +++ b/libstdc++-v3/include/c_global/csetjmp @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file csetjmp - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c setjmp.h, diff --git a/libstdc++-v3/include/c_global/csignal b/libstdc++-v3/include/c_global/csignal index 41af5e694a4..147b5b61859 100644 --- a/libstdc++-v3/include/c_global/csignal +++ b/libstdc++-v3/include/c_global/csignal @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file csignal - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c signal.h, diff --git a/libstdc++-v3/include/c_global/cstdarg b/libstdc++-v3/include/c_global/cstdarg index 73327b1a353..c61a866bfe7 100644 --- a/libstdc++-v3/include/c_global/cstdarg +++ b/libstdc++-v3/include/c_global/cstdarg @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cstdarg - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c stdarg.h, diff --git a/libstdc++-v3/include/c_global/cstdatomic b/libstdc++-v3/include/c_global/cstdatomic index 7489d97c07d..c2aea8f02c2 100644 --- a/libstdc++-v3/include/c_global/cstdatomic +++ b/libstdc++-v3/include/c_global/cstdatomic @@ -24,7 +24,7 @@ // <http://www.gnu.org/licenses/>. /** @file cstdatomic - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c stdatomic.h, diff --git a/libstdc++-v3/include/c_global/cstddef b/libstdc++-v3/include/c_global/cstddef index bb16e75e0ac..6beb52588bc 100644 --- a/libstdc++-v3/include/c_global/cstddef +++ b/libstdc++-v3/include/c_global/cstddef @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file cstddef - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c stddef.h, diff --git a/libstdc++-v3/include/c_global/cstdio b/libstdc++-v3/include/c_global/cstdio index ff5a635a152..b17f5ccf864 100644 --- a/libstdc++-v3/include/c_global/cstdio +++ b/libstdc++-v3/include/c_global/cstdio @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cstdio - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c stdio.h, diff --git a/libstdc++-v3/include/c_global/cstdlib b/libstdc++-v3/include/c_global/cstdlib index e252d089e75..0e0d7d5c18c 100644 --- a/libstdc++-v3/include/c_global/cstdlib +++ b/libstdc++-v3/include/c_global/cstdlib @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cstdlib - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c stdlib.h, diff --git a/libstdc++-v3/include/c_global/cstring b/libstdc++-v3/include/c_global/cstring index de0ce2425e3..acd6166b15f 100644 --- a/libstdc++-v3/include/c_global/cstring +++ b/libstdc++-v3/include/c_global/cstring @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file cstring - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c string.h, diff --git a/libstdc++-v3/include/c_global/ctime b/libstdc++-v3/include/c_global/ctime index e236cf48367..8430dc84234 100644 --- a/libstdc++-v3/include/c_global/ctime +++ b/libstdc++-v3/include/c_global/ctime @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/ctime - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c time.h, diff --git a/libstdc++-v3/include/c_global/cwchar b/libstdc++-v3/include/c_global/cwchar index f7f07c3caf5..f2f36cfc75c 100644 --- a/libstdc++-v3/include/c_global/cwchar +++ b/libstdc++-v3/include/c_global/cwchar @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cwchar - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c wchar.h, diff --git a/libstdc++-v3/include/c_global/cwctype b/libstdc++-v3/include/c_global/cwctype index 4e94fec3426..ffc75c82ba5 100644 --- a/libstdc++-v3/include/c_global/cwctype +++ b/libstdc++-v3/include/c_global/cwctype @@ -25,7 +25,7 @@ // <http://www.gnu.org/licenses/>. /** @file include/cwctype - * This is a Standard C++ Library file. You should @c #include this file + * This is a Standard C++ Library file. You should @c \#include this file * in your programs, rather than any of the "*.h" implementation files. * * This is the C++ version of the Standard C Library header @c wctype.h, diff --git a/libstdc++-v3/include/decimal/decimal b/libstdc++-v3/include/decimal/decimal new file mode 100644 index 00000000000..8ef5a91c0ca --- /dev/null +++ b/libstdc++-v3/include/decimal/decimal @@ -0,0 +1,482 @@ +// <decimal> -*- C++ -*- + +// Copyright (C) 2009 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 include/decimal/decimal + * This is a Standard C++ Library header. + */ + +// ISO/IEC TR 24733 +// Written by Janis Johnson <janis187@us.ibm.com> + +#ifndef _GLIBCXX_DECIMAL +#define _GLIBCXX_DECIMAL 1 + +#pragma GCC system_header + +#include <bits/c++config.h> + +#ifndef _GLIBCXX_USE_DECIMAL_FLOAT +#error This file requires compiler and library support for ISO/IEC TR 24733 \ +that is currently not available. +#endif + +namespace std +{ + /** + * @defgroup decimal Decimal Floating-Point Arithmetic + * @ingroup numerics + * + * Classes and functions for decimal floating-point arithmetic. + * @{ + */ + + /** @namespace std::decimal + * @brief ISO/IEC TR 24733 Decimal floating-point arithmetic. + */ +namespace decimal +{ + class decimal32; + class decimal64; + class decimal128; + + // 3.2.5 Initialization from coefficient and exponent. + static decimal32 make_decimal32(long long __coeff, int __exp); + static decimal32 make_decimal32(unsigned long long __coeff, int __exp); + static decimal64 make_decimal64(long long __coeff, int __exp); + static decimal64 make_decimal64(unsigned long long __coeff, int __exp); + static decimal128 make_decimal128(long long __coeff, int __exp); + static decimal128 make_decimal128(unsigned long long __coeff, int __exp); + + /// Non-conforming extension: Conversion to integral type. + long long decimal32_to_long_long(decimal32 __d); + long long decimal64_to_long_long(decimal64 __d); + long long decimal128_to_long_long(decimal128 __d); + long long decimal_to_long_long(decimal32 __d); + long long decimal_to_long_long(decimal64 __d); + long long decimal_to_long_long(decimal128 __d); + + // 3.2.6 Conversion to generic floating-point type. + float decimal32_to_float(decimal32 __d); + float decimal64_to_float(decimal64 __d); + float decimal128_to_float(decimal128 __d); + float decimal_to_float(decimal32 __d); + float decimal_to_float(decimal64 __d); + float decimal_to_float(decimal128 __d); + + double decimal32_to_double(decimal32 __d); + double decimal64_to_double(decimal64 __d); + double decimal128_to_double(decimal128 __d); + double decimal_to_double(decimal32 __d); + double decimal_to_double(decimal64 __d); + double decimal_to_double(decimal128 __d); + + long double decimal32_to_long_double(decimal32 __d); + long double decimal64_to_long_double(decimal64 __d); + long double decimal128_to_long_double(decimal128 __d); + long double decimal_to_long_double(decimal32 __d); + long double decimal_to_long_double(decimal64 __d); + long double decimal_to_long_double(decimal128 __d); + + // 3.2.7 Unary arithmetic operators. + decimal32 operator+(decimal32 __rhs); + decimal64 operator+(decimal64 __rhs); + decimal128 operator+(decimal128 __rhs); + decimal32 operator-(decimal32 __rhs); + decimal64 operator-(decimal64 __rhs); + decimal128 operator-(decimal128 __rhs); + + // 3.2.8 Binary arithmetic operators. +#define _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ + _T1 operator _Op(_T2 __lhs, _T3 __rhs); +#define _DECLARE_DECIMAL_BINARY_OP_WITH_INT(_Op, _Tp) \ + _Tp operator _Op(_Tp __lhs, int __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned int __rhs); \ + _Tp operator _Op(_Tp __lhs, long __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned long __rhs); \ + _Tp operator _Op(_Tp __lhs, long long __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned long long __rhs); \ + _Tp operator _Op(int __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned int __lhs, _Tp __rhs); \ + _Tp operator _Op(long __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned long __lhs, _Tp __rhs); \ + _Tp operator _Op(long long __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned long long __lhs, _Tp __rhs); + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) + +#undef _DECLARE_DECIMAL_BINARY_OP_WITH_DEC +#undef _DECLARE_DECIMAL_BINARY_OP_WITH_INT + + // 3.2.9 Comparison operators. +#define _DECLARE_DECIMAL_COMPARISON(_Op, _Tp) \ + bool operator _Op(_Tp __lhs, decimal32 __rhs); \ + bool operator _Op(_Tp __lhs, decimal64 __rhs); \ + bool operator _Op(_Tp __lhs, decimal128 __rhs); \ + bool operator _Op(_Tp __lhs, int __rhs); \ + bool operator _Op(_Tp __lhs, unsigned int __rhs); \ + bool operator _Op(_Tp __lhs, long __rhs); \ + bool operator _Op(_Tp __lhs, unsigned long __rhs); \ + bool operator _Op(_Tp __lhs, long long __rhs); \ + bool operator _Op(_Tp __lhs, unsigned long long __rhs); \ + bool operator _Op(int __lhs, _Tp __rhs); \ + bool operator _Op(unsigned int __lhs, _Tp __rhs); \ + bool operator _Op(long __lhs, _Tp __rhs); \ + bool operator _Op(unsigned long __lhs, _Tp __rhs); \ + bool operator _Op(long long __lhs, _Tp __rhs); \ + bool operator _Op(unsigned long long __lhs, _Tp __rhs); + + _DECLARE_DECIMAL_COMPARISON(==, decimal32) + _DECLARE_DECIMAL_COMPARISON(==, decimal64) + _DECLARE_DECIMAL_COMPARISON(==, decimal128) + + _DECLARE_DECIMAL_COMPARISON(!=, decimal32) + _DECLARE_DECIMAL_COMPARISON(!=, decimal64) + _DECLARE_DECIMAL_COMPARISON(!=, decimal128) + + _DECLARE_DECIMAL_COMPARISON(<, decimal32) + _DECLARE_DECIMAL_COMPARISON(<, decimal64) + _DECLARE_DECIMAL_COMPARISON(<, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>=, decimal32) + _DECLARE_DECIMAL_COMPARISON(>=, decimal64) + _DECLARE_DECIMAL_COMPARISON(>=, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>, decimal32) + _DECLARE_DECIMAL_COMPARISON(>, decimal64) + _DECLARE_DECIMAL_COMPARISON(>, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>=, decimal32) + _DECLARE_DECIMAL_COMPARISON(>=, decimal64) + _DECLARE_DECIMAL_COMPARISON(>=, decimal128) + +#undef _DECLARE_DECIMAL_COMPARISON + + /// 3.2.2 Class decimal32. + class decimal32 + { + public: + typedef float __decfloat32 __attribute__((mode(SD))); + + // 3.2.2.2 Construct/copy/destroy. + decimal32() : __val(0.e-101DF) {} + + // 3.2.2.3 Conversion from floating-point type. + explicit decimal32(decimal64 __d64); + explicit decimal32(decimal128 __d128); + explicit decimal32(float __r) : __val(__r) {} + explicit decimal32(double __r) : __val(__r) {} + explicit decimal32(long double __r) : __val(__r) {} + + // 3.2.2.4 Conversion from integral type. + decimal32(int __z) : __val(__z) {} + decimal32(unsigned int __z) : __val(__z) {} + decimal32(long __z) : __val(__z) {} + decimal32(unsigned long __z) : __val(__z) {} + decimal32(long long __z) : __val(__z) {} + decimal32(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal32(__decfloat32 __z) : __val(__z) {} + + // 3.2.2.5 Conversion to integral type. (DISABLED) + //operator long long() const { return (long long)__val; } + + // 3.2.2.6 Increment and decrement operators. + decimal32& operator++() + { + __val += 1; + return *this; + } + + decimal32 operator++(int) + { + decimal32 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal32& operator--() + { + __val -= 1; + return *this; + } + + decimal32 operator--(int) + { + decimal32 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.2.7 Compound assignment. +#define _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(_Op) \ + decimal32& operator _Op(decimal32 __rhs); \ + decimal32& operator _Op(decimal64 __rhs); \ + decimal32& operator _Op(decimal128 __rhs); \ + decimal32& operator _Op(int __rhs); \ + decimal32& operator _Op(unsigned int __rhs); \ + decimal32& operator _Op(long __rhs); \ + decimal32& operator _Op(unsigned long __rhs); \ + decimal32& operator _Op(long long __rhs); \ + decimal32& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT + + private: + __decfloat32 __val; + + public: + __decfloat32 __getval(void) { return __val; } + void __setval(__decfloat32 __x) { __val = __x; } + }; + + /// 3.2.3 Class decimal64. + class decimal64 + { + public: + typedef float __decfloat64 __attribute__((mode(DD))); + + // 3.2.3.2 Construct/copy/destroy. + decimal64() : __val(0.e-398dd) {} + + // 3.2.3.3 Conversion from floating-point type. + decimal64(decimal32 d32); + explicit decimal64(decimal128 d128); + explicit decimal64(float __r) : __val(__r) {} + explicit decimal64(double __r) : __val(__r) {} + explicit decimal64(long double __r) : __val(__r) {} + + // 3.2.3.4 Conversion from integral type. + decimal64(int __z) : __val(__z) {} + decimal64(unsigned int __z) : __val(__z) {} + decimal64(long __z) : __val(__z) {} + decimal64(unsigned long __z) : __val(__z) {} + decimal64(long long __z) : __val(__z) {} + decimal64(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal64(__decfloat64 __z) : __val(__z) {} + + // 3.2.3.5 Conversion to integral type. (DISABLED) + //operator long long() const { return (long long)__val; } + + // 3.2.3.6 Increment and decrement operators. + decimal64& operator++() + { + __val += 1; + return *this; + } + + decimal64 operator++(int) + { + decimal64 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal64& operator--() + { + __val -= 1; + return *this; + } + + decimal64 operator--(int) + { + decimal64 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.3.7 Compound assignment. +#define _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(_Op) \ + decimal64& operator _Op(decimal32 __rhs); \ + decimal64& operator _Op(decimal64 __rhs); \ + decimal64& operator _Op(decimal128 __rhs); \ + decimal64& operator _Op(int __rhs); \ + decimal64& operator _Op(unsigned int __rhs); \ + decimal64& operator _Op(long __rhs); \ + decimal64& operator _Op(unsigned long __rhs); \ + decimal64& operator _Op(long long __rhs); \ + decimal64& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT + + private: + __decfloat64 __val; + + public: + __decfloat64 __getval(void) { return __val; } + void __setval(__decfloat64 __x) { __val = __x; } + }; + + /// 3.2.4 Class decimal128. + class decimal128 + { + public: + typedef float __decfloat128 __attribute__((mode(TD))); + + // 3.2.4.2 Construct/copy/destroy. + decimal128() : __val(0.e-6176DL) {} + + // 3.2.4.3 Conversion from floating-point type. + decimal128(decimal32 d32); + decimal128(decimal64 d64); + explicit decimal128(float __r) : __val(__r) {} + explicit decimal128(double __r) : __val(__r) {} + explicit decimal128(long double __r) : __val(__r) {} + + + // 3.2.4.4 Conversion from integral type. + decimal128(int __z) : __val(__z) {} + decimal128(unsigned int __z) : __val(__z) {} + decimal128(long __z) : __val(__z) {} + decimal128(unsigned long __z) : __val(__z) {} + decimal128(long long __z) : __val(__z) {} + decimal128(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal128(__decfloat128 __z) : __val(__z) {} + + // 3.2.4.5 Conversion to integral type. (DISABLED) + //operator long long() const { return (long long)__val; } + + // 3.2.4.6 Increment and decrement operators. + decimal128& operator++() + { + __val += 1; + return *this; + } + + decimal128 operator++(int) + { + decimal128 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal128& operator--() + { + __val -= 1; + return *this; + } + + decimal128 operator--(int) + { + decimal128 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.4.7 Compound assignment. +#define _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(_Op) \ + decimal128& operator _Op(decimal32 __rhs); \ + decimal128& operator _Op(decimal64 __rhs); \ + decimal128& operator _Op(decimal128 __rhs); \ + decimal128& operator _Op(int __rhs); \ + decimal128& operator _Op(unsigned int __rhs); \ + decimal128& operator _Op(long __rhs); \ + decimal128& operator _Op(unsigned long __rhs); \ + decimal128& operator _Op(long long __rhs); \ + decimal128& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT + + private: + __decfloat128 __val; + + public: + __decfloat128 __getval(void) { return __val; } + void __setval(__decfloat128 __x) { __val = __x; } + }; + +#define _GLIBCXX_USE_DECIMAL_ 1 + +} // namespace decimal + // @} group decimal +} // namespace std + +#include <decimal/decimal.h> + +#endif /* _GLIBCXX_DECIMAL */ diff --git a/libstdc++-v3/include/decimal/decimal.h b/libstdc++-v3/include/decimal/decimal.h new file mode 100644 index 00000000000..45a6fbc20a8 --- /dev/null +++ b/libstdc++-v3/include/decimal/decimal.h @@ -0,0 +1,466 @@ +// decimal classes -*- C++ -*- + +// Copyright (C) 2009 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 bits/decimal.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ + +// ISO/IEC TR 24733 +// Written by Janis Johnson <janis187@us.ibm.com> + +#ifndef _GLIBCXX_DECIMAL_IMPL +#define _GLIBCXX_DECIMAL_IMPL 1 + +#pragma GCC system_header + +namespace std +{ +namespace decimal +{ + // ISO/IEC TR 24733 3.2.[234].1 Construct/copy/destroy. + + inline decimal32::decimal32(decimal64 __r) : __val(__r.__getval()) {} + inline decimal32::decimal32(decimal128 __r) : __val(__r.__getval()) {} + inline decimal64::decimal64(decimal32 __r) : __val(__r.__getval()) {} + inline decimal64::decimal64(decimal128 __r) : __val(__r.__getval()) {} + inline decimal128::decimal128(decimal32 __r) : __val(__r.__getval()) {} + inline decimal128::decimal128(decimal64 __r) : __val(__r.__getval()) {} + + // ISO/IEC TR 24733 3.2.[234].6 Compound assignment. + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, _T2) \ + inline _T1& _T1::operator _Op1(_T2 __rhs) \ + { \ + __setval(__getval() _Op2 __rhs.__getval()); \ + return *this; \ + } + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, _T2) \ + inline _T1& _T1::operator _Op1(_T2 __rhs) \ + { \ + __setval(__getval() _Op2 __rhs); \ + return *this; \ + } + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(_Op1, _Op2, _T1) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal32) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal64) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal128) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, int) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned int) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long)\ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long long) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long long) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal32) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal64) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal128) + +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS + + // Extension: Conversion to integral type. + + inline long long decimal32_to_long_long(decimal32 __d) + { return (long long)__d.__getval(); } + + inline long long decimal64_to_long_long(decimal64 __d) + { return (long long)__d.__getval(); } + + inline long long decimal128_to_long_long(decimal128 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal32 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal64 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal128 __d) + { return (long long)__d.__getval(); } + + // ISO/IEC TR 24733 3.2.5 Initialization from coefficient and exponent. + + static decimal32 make_decimal32(long long __coeff, int __exponent) + { + decimal32 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DF; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DF; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal32 make_decimal32(unsigned long long __coeff, int __exponent) + { + decimal32 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DF; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DF; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal64 make_decimal64(long long __coeff, int __exponent) + { + decimal64 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DD; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DD; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal64 make_decimal64(unsigned long long __coeff, int __exponent) + { + decimal64 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DD; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DD; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal128 make_decimal128(long long __coeff, int __exponent) + { + decimal128 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DL; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DL; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal128 make_decimal128(unsigned long long __coeff, int __exponent) + { + decimal128 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DL; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DL; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + // ISO/IEC TR 24733 3.2.6 Conversion to generic floating-point type. + + inline float decimal32_to_float(decimal32 __d) + { return (float)__d.__getval(); } + + inline float decimal64_to_float(decimal64 __d) + { return (float)__d.__getval(); } + + inline float decimal128_to_float(decimal128 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal32 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal64 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal128 __d) + { return (float)__d.__getval(); } + + inline double decimal32_to_double(decimal32 __d) + { return (double)__d.__getval(); } + + inline double decimal64_to_double(decimal64 __d) + { return (double)__d.__getval(); } + + inline double decimal128_to_double(decimal128 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal32 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal64 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal128 __d) + { return (double)__d.__getval(); } + + inline long double decimal32_to_long_double(decimal32 __d) + { return (long double)__d.__getval(); } + + inline long double decimal64_to_long_double(decimal64 __d) + { return (long double)__d.__getval(); } + + inline long double decimal128_to_long_double(decimal128 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal32 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal64 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal128 __d) + { return (long double)__d.__getval(); } + + // ISO/IEC TR 24733 3.2.7 Unary arithmetic operators. + +#define _DEFINE_DECIMAL_UNARY_OP(_Op, _Tp) \ + inline _Tp operator _Op(_Tp __rhs) \ + { \ + _Tp __tmp; \ + __tmp.__setval(0 _Op __rhs.__getval()); \ + return __tmp; \ + } + + _DEFINE_DECIMAL_UNARY_OP(+, decimal32) + _DEFINE_DECIMAL_UNARY_OP(+, decimal64) + _DEFINE_DECIMAL_UNARY_OP(+, decimal128) + _DEFINE_DECIMAL_UNARY_OP(-, decimal32) + _DEFINE_DECIMAL_UNARY_OP(-, decimal64) + _DEFINE_DECIMAL_UNARY_OP(-, decimal128) + +#undef _DEFINE_DECIMAL_UNARY_OP + + // ISO/IEC TR 24733 3.2.8 Binary arithmetic operators. + +#define _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ + inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_BOTH(_Op, _T1, _T2, _T3) \ + inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, _T2) \ + inline _T1 operator _Op(_T1 __lhs, _T2 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, _T2) \ + inline _T1 operator _Op(_T2 __lhs, _T1 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_WITH_INT(_Op, _T1) \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, int); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned int); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, int); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned int); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long long); \ + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) + +#undef _DEFINE_DECIMAL_BINARY_OP_WITH_DEC +#undef _DEFINE_DECIMAL_BINARY_OP_BOTH +#undef _DEFINE_DECIMAL_BINARY_OP_LHS +#undef _DEFINE_DECIMAL_BINARY_OP_RHS +#undef _DEFINE_DECIMAL_BINARY_OP_WITH_INT + + // ISO/IEC TR 24733 3.2.9 Comparison operators. + +#define _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs.__getval() _Op __rhs.__getval(); } + +#define _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs.__getval() _Op __rhs; } + +#define _DEFINE_DECIMAL_COMPARISON_RHS(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs _Op __rhs.__getval(); } + +#define _DEFINE_DECIMAL_COMPARISONS(_Op, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal32) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal64) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal128) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, int) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned int) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long long) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, int, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned int, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long long, _Tp) + + _DEFINE_DECIMAL_COMPARISONS(==, decimal32) + _DEFINE_DECIMAL_COMPARISONS(==, decimal64) + _DEFINE_DECIMAL_COMPARISONS(==, decimal128) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal128) + _DEFINE_DECIMAL_COMPARISONS(<, decimal32) + _DEFINE_DECIMAL_COMPARISONS(<, decimal64) + _DEFINE_DECIMAL_COMPARISONS(<, decimal128) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal128) + _DEFINE_DECIMAL_COMPARISONS(>, decimal32) + _DEFINE_DECIMAL_COMPARISONS(>, decimal64) + _DEFINE_DECIMAL_COMPARISONS(>, decimal128) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal128) + +#undef _DEFINE_DECIMAL_COMPARISON_BOTH +#undef _DEFINE_DECIMAL_COMPARISON_LHS +#undef _DEFINE_DECIMAL_COMPARISON_RHS +#undef _DEFINE_DECIMAL_COMPARISONS + +} // namespace decimal +} // namespace std + +#endif /* _GLIBCXX_DECIMAL_IMPL */ diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h index f6790d00043..d91d9aa5cc6 100644 --- a/libstdc++-v3/include/ext/bitmap_allocator.h +++ b/libstdc++-v3/include/ext/bitmap_allocator.h @@ -104,20 +104,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) // insert(iterator, const_reference), erase(iterator), // begin(), end(), back(), operator[]. - __mini_vector() : _M_start(0), _M_finish(0), - _M_end_of_storage(0) - { } - -#if 0 - ~__mini_vector() - { - if (this->_M_start) - { - this->deallocate(this->_M_start, this->_M_end_of_storage - - this->_M_start); - } - } -#endif + __mini_vector() + : _M_start(0), _M_finish(0), _M_end_of_storage(0) { } size_type size() const throw() @@ -276,15 +264,6 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) return __first; } - template<typename _InputIterator, typename _Predicate> - inline _InputIterator - __find_if(_InputIterator __first, _InputIterator __last, _Predicate __p) - { - while (__first != __last && !__p(*__first)) - ++__first; - return __first; - } - /** @brief The number of Blocks pointed to by the address pair * passed to the function. */ @@ -380,12 +359,10 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) // is equal to the number of Objects that the current Block can // store, then there is definitely no space for another single // object, so just return false. - _Counter_type __diff = - __gnu_cxx::__detail::__num_bitmaps(__bp); + _Counter_type __diff = __detail::__num_bitmaps(__bp); if (*(reinterpret_cast<size_t*> - (__bp.first) - (__diff + 1)) - == __gnu_cxx::__detail::__num_blocks(__bp)) + (__bp.first) - (__diff + 1)) == __detail::__num_blocks(__bp)) return false; size_t* __rover = reinterpret_cast<size_t*>(__bp.first) - 1; @@ -402,7 +379,6 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) } return false; } - size_t* _M_get() const throw() @@ -413,7 +389,6 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) { return _M_data_offset * size_t(bits_per_block); } }; - /** @class _Bitmap_counter bitmap_allocator.h bitmap_allocator.h * * @brief The bitmap counter which acts as the bitmap @@ -424,11 +399,11 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) template<typename _Tp> class _Bitmap_counter { - typedef typename __detail::__mini_vector<typename std::pair<_Tp, _Tp> > - _BPVector; + typedef typename + __detail::__mini_vector<typename std::pair<_Tp, _Tp> > _BPVector; typedef typename _BPVector::size_type _Index_type; typedef _Tp pointer; - + _BPVector& _M_vbp; size_t* _M_curr_bmap; size_t* _M_last_bmap_in_block; @@ -613,7 +588,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) } // Just add the block to the list of free lists unconditionally. - iterator __temp = __gnu_cxx::__detail::__lower_bound + iterator __temp = __detail::__lower_bound (__free_list.begin(), __free_list.end(), *__addr, _LT_pointer_compare()); @@ -656,7 +631,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) _M_insert(size_t* __addr) throw() { #if defined __GTHREADS - __gnu_cxx::__scoped_lock __bfl_lock(_M_get_mutex()); + __scoped_lock __bfl_lock(_M_get_mutex()); #endif // Call _M_validate to decide what should be done with // this particular free list. @@ -747,8 +722,18 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) typedef typename std::pair<_Alloc_block*, _Alloc_block*> _Block_pair; - typedef typename - __detail::__mini_vector<_Block_pair> _BPVector; + typedef typename __detail::__mini_vector<_Block_pair> _BPVector; + typedef typename _BPVector::iterator _BPiter; + + template<typename _Predicate> + static _BPiter + _S_find(_Predicate __p) + { + _BPiter __first = _S_mem_blocks.begin(); + while (__first != _S_mem_blocks.end() && !__p(*__first)) + ++__first; + return __first; + } #if defined _GLIBCXX_DEBUG // Complexity: O(lg(N)). Where, N is the number of block of size @@ -756,14 +741,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) void _S_check_for_free_blocks() throw() { - typedef typename - __gnu_cxx::__detail::_Ffit_finder<_Alloc_block*> _FFF; - _FFF __fff; - typedef typename _BPVector::iterator _BPiter; - _BPiter __bpi = - __gnu_cxx::__detail::__find_if - (_S_mem_blocks.begin(), _S_mem_blocks.end(), - __gnu_cxx::__detail::_Functor_Ref<_FFF>(__fff)); + typedef typename __detail::_Ffit_finder<_Alloc_block*> _FFF; + _BPiter __bpi = _S_find(_FFF()); _GLIBCXX_DEBUG_ASSERT(__bpi == _S_mem_blocks.end()); } @@ -793,9 +772,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) + _S_block_size * sizeof(_Alloc_block) + __num_bitmaps * sizeof(size_t); - size_t* __temp = - reinterpret_cast<size_t*> - (this->_M_get(__size_to_allocate)); + size_t* __temp = + reinterpret_cast<size_t*>(this->_M_get(__size_to_allocate)); *__temp = 0; ++__temp; @@ -810,20 +788,15 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) // Fill the Vector with this information. _S_mem_blocks.push_back(__bp); - size_t __bit_mask = 0; // 0 Indicates all Allocated. - __bit_mask = ~__bit_mask; // 1 Indicates all Free. - for (size_t __i = 0; __i < __num_bitmaps; ++__i) - __temp[__i] = __bit_mask; + __temp[__i] = ~static_cast<size_t>(0); // 1 Indicates all Free. _S_block_size *= 2; } - static _BPVector _S_mem_blocks; static size_t _S_block_size; - static __gnu_cxx::__detail:: - _Bitmap_counter<_Alloc_block*> _S_last_request; + static __detail::_Bitmap_counter<_Alloc_block*> _S_last_request; static typename _BPVector::size_type _S_last_dealloc_index; #if defined __GTHREADS static __mutex_type _S_mut; @@ -848,7 +821,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) _M_allocate_single_object() throw(std::bad_alloc) { #if defined __GTHREADS - __gnu_cxx::__scoped_lock __bit_lock(_S_mut); + __scoped_lock __bit_lock(_S_mut); #endif // The algorithm is something like this: The last_request @@ -866,21 +839,14 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) // dereference if tinkered with. while (_S_last_request._M_finished() == false && (*(_S_last_request._M_get()) == 0)) - { - _S_last_request.operator++(); - } + _S_last_request.operator++(); if (__builtin_expect(_S_last_request._M_finished() == true, false)) { // Fall Back to First Fit algorithm. - typedef typename - __gnu_cxx::__detail::_Ffit_finder<_Alloc_block*> _FFF; + typedef typename __detail::_Ffit_finder<_Alloc_block*> _FFF; _FFF __fff; - typedef typename _BPVector::iterator _BPiter; - _BPiter __bpi = - __gnu_cxx::__detail::__find_if - (_S_mem_blocks.begin(), _S_mem_blocks.end(), - __gnu_cxx::__detail::_Functor_Ref<_FFF>(__fff)); + _BPiter __bpi = _S_find(__detail::_Functor_Ref<_FFF>(__fff)); if (__bpi != _S_mem_blocks.end()) { @@ -897,8 +863,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) (__bpi->first + __fff._M_offset() + __nz_bit); size_t* __puse_count = reinterpret_cast<size_t*> - (__bpi->first) - - (__gnu_cxx::__detail::__num_bitmaps(*__bpi) + 1); + (__bpi->first) - (__detail::__num_bitmaps(*__bpi) + 1); ++(*__puse_count); return __ret; @@ -927,7 +892,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) size_t* __puse_count = reinterpret_cast<size_t*> (_S_mem_blocks[_S_last_request._M_where()].first) - - (__gnu_cxx::__detail:: + - (__detail:: __num_bitmaps(_S_mem_blocks[_S_last_request._M_where()]) + 1); ++(*__puse_count); @@ -946,7 +911,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) _M_deallocate_single_object(pointer __p) throw() { #if defined __GTHREADS - __gnu_cxx::__scoped_lock __bit_lock(_S_mut); + __scoped_lock __bit_lock(_S_mut); #endif _Alloc_block* __real_p = reinterpret_cast<_Alloc_block*>(__p); @@ -958,9 +923,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index >= 0); - - if (__gnu_cxx::__detail::_Inclusive_between<_Alloc_block*> - (__real_p) (_S_mem_blocks[_S_last_dealloc_index])) + __detail::_Inclusive_between<_Alloc_block*> __ibt(__real_p); + if (__ibt(_S_mem_blocks[_S_last_dealloc_index])) { _GLIBCXX_DEBUG_ASSERT(_S_last_dealloc_index <= _S_mem_blocks.size() - 1); @@ -971,11 +935,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) } else { - _Iterator _iter = __gnu_cxx::__detail:: - __find_if(_S_mem_blocks.begin(), - _S_mem_blocks.end(), - __gnu_cxx::__detail:: - _Inclusive_between<_Alloc_block*>(__real_p)); + _Iterator _iter = _S_find(__ibt); _GLIBCXX_DEBUG_ASSERT(_iter != _S_mem_blocks.end()); @@ -995,7 +955,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) __detail::__bit_free(__bitmapC, __rotate); size_t* __puse_count = reinterpret_cast<size_t*> (_S_mem_blocks[__diff].first) - - (__gnu_cxx::__detail::__num_bitmaps(_S_mem_blocks[__diff]) + 1); + - (__detail::__num_bitmaps(_S_mem_blocks[__diff]) + 1); _GLIBCXX_DEBUG_ASSERT(*__puse_count != 0); @@ -1127,12 +1087,12 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 2 * size_t(__detail::bits_per_block); template<typename _Tp> - typename __gnu_cxx::bitmap_allocator<_Tp>::_BPVector::size_type + typename bitmap_allocator<_Tp>::_BPVector::size_type bitmap_allocator<_Tp>::_S_last_dealloc_index = 0; template<typename _Tp> - __gnu_cxx::__detail::_Bitmap_counter - <typename bitmap_allocator<_Tp>::_Alloc_block*> + __detail::_Bitmap_counter + <typename bitmap_allocator<_Tp>::_Alloc_block*> bitmap_allocator<_Tp>::_S_last_request(_S_mem_blocks); #if defined __GTHREADS diff --git a/libstdc++-v3/include/parallel/balanced_quicksort.h b/libstdc++-v3/include/parallel/balanced_quicksort.h index 85e4d699e26..f3ac555908f 100644 --- a/libstdc++-v3/include/parallel/balanced_quicksort.h +++ b/libstdc++-v3/include/parallel/balanced_quicksort.h @@ -57,436 +57,435 @@ namespace __gnu_parallel { -/** @brief Information local to one thread in the parallel quicksort run. */ -template<typename _RAIter> - struct _QSBThreadLocal - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; - - /** @brief Continuous part of the sequence, described by an - iterator pair. */ - typedef std::pair<_RAIter, _RAIter> _Piece; - - /** @brief Initial piece to work on. */ - _Piece _M_initial; - - /** @brief Work-stealing queue. */ - _RestrictedBoundedConcurrentQueue<_Piece> _M_leftover_parts; - - /** @brief Number of threads involved in this algorithm. */ - _ThreadIndex _M_num_threads; - - /** @brief Pointer to a counter of elements left over to sort. */ - volatile _DifferenceType* _M_elements_leftover; - - /** @brief The complete sequence to sort. */ - _Piece _M_global; - - /** @brief Constructor. - * @param __queue_size size of the work-stealing queue. */ - _QSBThreadLocal(int __queue_size) : _M_leftover_parts(__queue_size) { } - }; - -/** @brief Balanced quicksort divide step. - * @param __begin Begin iterator of subsequence. - * @param __end End iterator of subsequence. - * @param __comp Comparator. - * @param __num_threads Number of threads that are allowed to work on - * this part. - * @pre @__c (__end-__begin)>=1 */ -template<typename _RAIter, typename _Compare> - typename std::iterator_traits<_RAIter>::difference_type - __qsb_divide(_RAIter __begin, _RAIter __end, - _Compare __comp, _ThreadIndex __num_threads) - { - _GLIBCXX_PARALLEL_ASSERT(__num_threads > 0); - - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _RAIter __pivot_pos = - __median_of_three_iterators(__begin, __begin + (__end - __begin) / 2, - __end - 1, __comp); + /** @brief Information local to one thread in the parallel quicksort run. */ + template<typename _RAIter> + struct _QSBThreadLocal + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + + /** @brief Continuous part of the sequence, described by an + iterator pair. */ + typedef std::pair<_RAIter, _RAIter> _Piece; + + /** @brief Initial piece to work on. */ + _Piece _M_initial; + + /** @brief Work-stealing queue. */ + _RestrictedBoundedConcurrentQueue<_Piece> _M_leftover_parts; + + /** @brief Number of threads involved in this algorithm. */ + _ThreadIndex _M_num_threads; + + /** @brief Pointer to a counter of elements left over to sort. */ + volatile _DifferenceType* _M_elements_leftover; + + /** @brief The complete sequence to sort. */ + _Piece _M_global; + + /** @brief Constructor. + * @param __queue_size size of the work-stealing queue. */ + _QSBThreadLocal(int __queue_size) : _M_leftover_parts(__queue_size) { } + }; + + /** @brief Balanced quicksort divide step. + * @param __begin Begin iterator of subsequence. + * @param __end End iterator of subsequence. + * @param __comp Comparator. + * @param __num_threads Number of threads that are allowed to work on + * this part. + * @pre @c (__end-__begin)>=1 */ + template<typename _RAIter, typename _Compare> + typename std::iterator_traits<_RAIter>::difference_type + __qsb_divide(_RAIter __begin, _RAIter __end, + _Compare __comp, _ThreadIndex __num_threads) + { + _GLIBCXX_PARALLEL_ASSERT(__num_threads > 0); + + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + + _RAIter __pivot_pos = + __median_of_three_iterators(__begin, __begin + (__end - __begin) / 2, + __end - 1, __comp); #if defined(_GLIBCXX_ASSERTIONS) - // Must be in between somewhere. - _DifferenceType __n = __end - __begin; - - _GLIBCXX_PARALLEL_ASSERT( - (!__comp(*__pivot_pos, *__begin) && - !__comp(*(__begin + __n / 2), *__pivot_pos)) - || (!__comp(*__pivot_pos, *__begin) && - !__comp(*(__end - 1), *__pivot_pos)) - || (!__comp(*__pivot_pos, *(__begin + __n / 2)) && - !__comp(*__begin, *__pivot_pos)) - || (!__comp(*__pivot_pos, *(__begin + __n / 2)) && - !__comp(*(__end - 1), *__pivot_pos)) - || (!__comp(*__pivot_pos, *(__end - 1)) && - !__comp(*__begin, *__pivot_pos)) - || (!__comp(*__pivot_pos, *(__end - 1)) && - !__comp(*(__begin + __n / 2), *__pivot_pos))); + // Must be in between somewhere. + _DifferenceType __n = __end - __begin; + + _GLIBCXX_PARALLEL_ASSERT((!__comp(*__pivot_pos, *__begin) + && !__comp(*(__begin + __n / 2), + *__pivot_pos)) + || (!__comp(*__pivot_pos, *__begin) + && !__comp(*(__end - 1), *__pivot_pos)) + || (!__comp(*__pivot_pos, *(__begin + __n / 2)) + && !__comp(*__begin, *__pivot_pos)) + || (!__comp(*__pivot_pos, *(__begin + __n / 2)) + && !__comp(*(__end - 1), *__pivot_pos)) + || (!__comp(*__pivot_pos, *(__end - 1)) + && !__comp(*__begin, *__pivot_pos)) + || (!__comp(*__pivot_pos, *(__end - 1)) + && !__comp(*(__begin + __n / 2), + *__pivot_pos))); #endif - // Swap pivot value to end. - if (__pivot_pos != (__end - 1)) - std::swap(*__pivot_pos, *(__end - 1)); - __pivot_pos = __end - 1; + // Swap pivot value to end. + if (__pivot_pos != (__end - 1)) + std::swap(*__pivot_pos, *(__end - 1)); + __pivot_pos = __end - 1; - __gnu_parallel::binder2nd<_Compare, _ValueType, _ValueType, bool> - __pred(__comp, *__pivot_pos); + __gnu_parallel::binder2nd<_Compare, _ValueType, _ValueType, bool> + __pred(__comp, *__pivot_pos); - // Divide, returning __end - __begin - 1 in the worst case. - _DifferenceType __split_pos = __parallel_partition( - __begin, __end - 1, __pred, __num_threads); + // Divide, returning __end - __begin - 1 in the worst case. + _DifferenceType __split_pos = __parallel_partition(__begin, __end - 1, + __pred, + __num_threads); - // Swap back pivot to middle. - std::swap(*(__begin + __split_pos), *__pivot_pos); - __pivot_pos = __begin + __split_pos; + // Swap back pivot to middle. + std::swap(*(__begin + __split_pos), *__pivot_pos); + __pivot_pos = __begin + __split_pos; #if _GLIBCXX_ASSERTIONS - _RAIter __r; - for (__r = __begin; __r != __pivot_pos; ++__r) - _GLIBCXX_PARALLEL_ASSERT(__comp(*__r, *__pivot_pos)); - for (; __r != __end; ++__r) - _GLIBCXX_PARALLEL_ASSERT(!__comp(*__r, *__pivot_pos)); + _RAIter __r; + for (__r = __begin; __r != __pivot_pos; ++__r) + _GLIBCXX_PARALLEL_ASSERT(__comp(*__r, *__pivot_pos)); + for (; __r != __end; ++__r) + _GLIBCXX_PARALLEL_ASSERT(!__comp(*__r, *__pivot_pos)); #endif - return __split_pos; - } - -/** @brief Quicksort conquer step. - * @param __tls Array of thread-local storages. - * @param __begin Begin iterator of subsequence. - * @param __end End iterator of subsequence. - * @param __comp Comparator. - * @param __iam Number of the thread processing this function. - * @param __num_threads - * Number of threads that are allowed to work on this part. */ -template<typename _RAIter, typename _Compare> - void - __qsb_conquer(_QSBThreadLocal<_RAIter>** __tls, - _RAIter __begin, _RAIter __end, - _Compare __comp, - _ThreadIndex __iam, _ThreadIndex __num_threads, - bool __parent_wait) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _DifferenceType __n = __end - __begin; - - if (__num_threads <= 1 || __n <= 1) - { - __tls[__iam]->_M_initial.first = __begin; - __tls[__iam]->_M_initial.second = __end; + return __split_pos; + } - __qsb_local_sort_with_helping(__tls, __comp, __iam, __parent_wait); + /** @brief Quicksort conquer step. + * @param __tls Array of thread-local storages. + * @param __begin Begin iterator of subsequence. + * @param __end End iterator of subsequence. + * @param __comp Comparator. + * @param __iam Number of the thread processing this function. + * @param __num_threads + * Number of threads that are allowed to work on this part. */ + template<typename _RAIter, typename _Compare> + void + __qsb_conquer(_QSBThreadLocal<_RAIter>** __tls, + _RAIter __begin, _RAIter __end, + _Compare __comp, + _ThreadIndex __iam, _ThreadIndex __num_threads, + bool __parent_wait) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; - return; - } + _DifferenceType __n = __end - __begin; + + if (__num_threads <= 1 || __n <= 1) + { + __tls[__iam]->_M_initial.first = __begin; + __tls[__iam]->_M_initial.second = __end; + + __qsb_local_sort_with_helping(__tls, __comp, __iam, __parent_wait); + + return; + } - // Divide step. - _DifferenceType __split_pos = - __qsb_divide(__begin, __end, __comp, __num_threads); + // Divide step. + _DifferenceType __split_pos = + __qsb_divide(__begin, __end, __comp, __num_threads); #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(0 <= __split_pos && - __split_pos < (__end - __begin)); + _GLIBCXX_PARALLEL_ASSERT(0 <= __split_pos && + __split_pos < (__end - __begin)); #endif - _ThreadIndex __num_threads_leftside = - std::max<_ThreadIndex>(1, std::min<_ThreadIndex>( - __num_threads - 1, __split_pos * __num_threads / __n)); + _ThreadIndex + __num_threads_leftside = std::max<_ThreadIndex> + (1, std::min<_ThreadIndex>(__num_threads - 1, __split_pos + * __num_threads / __n)); -# pragma omp atomic - *__tls[__iam]->_M_elements_leftover -= (_DifferenceType)1; +# pragma omp atomic + *__tls[__iam]->_M_elements_leftover -= (_DifferenceType)1; - // Conquer step. -# pragma omp parallel num_threads(2) - { - bool __wait; - if(omp_get_num_threads() < 2) - __wait = false; - else - __wait = __parent_wait; - -# pragma omp sections - { + // Conquer step. +# pragma omp parallel num_threads(2) + { + bool __wait; + if(omp_get_num_threads() < 2) + __wait = false; + else + __wait = __parent_wait; + +# pragma omp sections + { # pragma omp section - { - __qsb_conquer(__tls, __begin, __begin + __split_pos, __comp, - __iam, - __num_threads_leftside, - __wait); - __wait = __parent_wait; - } - // The pivot_pos is left in place, to ensure termination. + { + __qsb_conquer(__tls, __begin, __begin + __split_pos, __comp, + __iam, __num_threads_leftside, __wait); + __wait = __parent_wait; + } + // The pivot_pos is left in place, to ensure termination. # pragma omp section - { - __qsb_conquer(__tls, __begin + __split_pos + 1, __end, __comp, - __iam + __num_threads_leftside, - __num_threads - __num_threads_leftside, - __wait); - __wait = __parent_wait; - } - } + { + __qsb_conquer(__tls, __begin + __split_pos + 1, __end, __comp, + __iam + __num_threads_leftside, + __num_threads - __num_threads_leftside, __wait); + __wait = __parent_wait; + } + } + } } - } - -/** - * @brief Quicksort step doing load-balanced local sort. - * @param __tls Array of thread-local storages. - * @param __comp Comparator. - * @param __iam Number of the thread processing this function. - */ -template<typename _RAIter, typename _Compare> - void - __qsb_local_sort_with_helping(_QSBThreadLocal<_RAIter>** __tls, - _Compare& __comp, int __iam, bool __wait) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - typedef std::pair<_RAIter, _RAIter> _Piece; - - _QSBThreadLocal<_RAIter>& __tl = *__tls[__iam]; - - _DifferenceType __base_case_n = - _Settings::get().sort_qsb_base_case_maximal_n; - if (__base_case_n < 2) - __base_case_n = 2; - _ThreadIndex __num_threads = __tl._M_num_threads; - - // Every thread has its own random number generator. - _RandomNumber __rng(__iam + 1); - - _Piece __current = __tl._M_initial; - - _DifferenceType __elements_done = 0; + + /** + * @brief Quicksort step doing load-balanced local sort. + * @param __tls Array of thread-local storages. + * @param __comp Comparator. + * @param __iam Number of the thread processing this function. + */ + template<typename _RAIter, typename _Compare> + void + __qsb_local_sort_with_helping(_QSBThreadLocal<_RAIter>** __tls, + _Compare& __comp, int __iam, bool __wait) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef std::pair<_RAIter, _RAIter> _Piece; + + _QSBThreadLocal<_RAIter>& __tl = *__tls[__iam]; + + _DifferenceType + __base_case_n = _Settings::get().sort_qsb_base_case_maximal_n; + if (__base_case_n < 2) + __base_case_n = 2; + _ThreadIndex __num_threads = __tl._M_num_threads; + + // Every thread has its own random number generator. + _RandomNumber __rng(__iam + 1); + + _Piece __current = __tl._M_initial; + + _DifferenceType __elements_done = 0; #if _GLIBCXX_ASSERTIONS - _DifferenceType __total_elements_done = 0; + _DifferenceType __total_elements_done = 0; #endif - for (;;) - { - // Invariant: __current must be a valid (maybe empty) range. - _RAIter __begin = __current.first, __end = __current.second; - _DifferenceType __n = __end - __begin; - - if (__n > __base_case_n) - { - // Divide. - _RAIter __pivot_pos = __begin + __rng(__n); - - // Swap __pivot_pos value to end. - if (__pivot_pos != (__end - 1)) - std::swap(*__pivot_pos, *(__end - 1)); - __pivot_pos = __end - 1; - - __gnu_parallel::binder2nd - <_Compare, _ValueType, _ValueType, bool> - __pred(__comp, *__pivot_pos); - - // Divide, leave pivot unchanged in last place. - _RAIter __split_pos1, __split_pos2; - __split_pos1 = - __gnu_sequential::partition(__begin, __end - 1, __pred); - - // Left side: < __pivot_pos; __right side: >= __pivot_pos. + for (;;) + { + // Invariant: __current must be a valid (maybe empty) range. + _RAIter __begin = __current.first, __end = __current.second; + _DifferenceType __n = __end - __begin; + + if (__n > __base_case_n) + { + // Divide. + _RAIter __pivot_pos = __begin + __rng(__n); + + // Swap __pivot_pos value to end. + if (__pivot_pos != (__end - 1)) + std::swap(*__pivot_pos, *(__end - 1)); + __pivot_pos = __end - 1; + + __gnu_parallel::binder2nd + <_Compare, _ValueType, _ValueType, bool> + __pred(__comp, *__pivot_pos); + + // Divide, leave pivot unchanged in last place. + _RAIter __split_pos1, __split_pos2; + __split_pos1 = __gnu_sequential::partition(__begin, __end - 1, + __pred); + + // Left side: < __pivot_pos; __right side: >= __pivot_pos. #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(__begin <= __split_pos1 - && __split_pos1 < __end); + _GLIBCXX_PARALLEL_ASSERT(__begin <= __split_pos1 + && __split_pos1 < __end); #endif - // Swap pivot back to middle. - if (__split_pos1 != __pivot_pos) - std::swap(*__split_pos1, *__pivot_pos); - __pivot_pos = __split_pos1; - - // In case all elements are equal, __split_pos1 == 0. - if ((__split_pos1 + 1 - __begin) < (__n >> 7) - || (__end - __split_pos1) < (__n >> 7)) - { - // Very unequal split, one part smaller than one 128th - // elements not strictly larger than the pivot. - __gnu_parallel::__unary_negate<__gnu_parallel::__binder1st - <_Compare, _ValueType, _ValueType, bool>, _ValueType> - __pred(__gnu_parallel::__binder1st - <_Compare, _ValueType, _ValueType, bool>( - __comp, *__pivot_pos)); - - // Find other end of pivot-equal range. - __split_pos2 = __gnu_sequential::partition(__split_pos1 + 1, - __end, __pred); - } - else - // Only skip the pivot. - __split_pos2 = __split_pos1 + 1; - - // Elements equal to pivot are done. - __elements_done += (__split_pos2 - __split_pos1); + // Swap pivot back to middle. + if (__split_pos1 != __pivot_pos) + std::swap(*__split_pos1, *__pivot_pos); + __pivot_pos = __split_pos1; + + // In case all elements are equal, __split_pos1 == 0. + if ((__split_pos1 + 1 - __begin) < (__n >> 7) + || (__end - __split_pos1) < (__n >> 7)) + { + // Very unequal split, one part smaller than one 128th + // elements not strictly larger than the pivot. + __gnu_parallel::__unary_negate<__gnu_parallel::__binder1st + <_Compare, _ValueType, _ValueType, bool>, _ValueType> + __pred(__gnu_parallel::__binder1st + <_Compare, _ValueType, _ValueType, bool> + (__comp, *__pivot_pos)); + + // Find other end of pivot-equal range. + __split_pos2 = __gnu_sequential::partition(__split_pos1 + 1, + __end, __pred); + } + else + // Only skip the pivot. + __split_pos2 = __split_pos1 + 1; + + // Elements equal to pivot are done. + __elements_done += (__split_pos2 - __split_pos1); #if _GLIBCXX_ASSERTIONS - __total_elements_done += (__split_pos2 - __split_pos1); + __total_elements_done += (__split_pos2 - __split_pos1); #endif - // Always push larger part onto stack. - if (((__split_pos1 + 1) - __begin) < (__end - (__split_pos2))) - { - // Right side larger. - if ((__split_pos2) != __end) - __tl._M_leftover_parts.push_front( - std::make_pair(__split_pos2, __end)); - - //__current.first = __begin; //already set anyway - __current.second = __split_pos1; - continue; - } - else - { - // Left side larger. - if (__begin != __split_pos1) - __tl._M_leftover_parts.push_front(std::make_pair(__begin, - __split_pos1)); - - __current.first = __split_pos2; - //__current.second = __end; //already set anyway - continue; - } - } - else - { - __gnu_sequential::sort(__begin, __end, __comp); - __elements_done += __n; + // Always push larger part onto stack. + if (((__split_pos1 + 1) - __begin) < (__end - (__split_pos2))) + { + // Right side larger. + if ((__split_pos2) != __end) + __tl._M_leftover_parts.push_front + (std::make_pair(__split_pos2, __end)); + + //__current.first = __begin; //already set anyway + __current.second = __split_pos1; + continue; + } + else + { + // Left side larger. + if (__begin != __split_pos1) + __tl._M_leftover_parts.push_front(std::make_pair + (__begin, __split_pos1)); + + __current.first = __split_pos2; + //__current.second = __end; //already set anyway + continue; + } + } + else + { + __gnu_sequential::sort(__begin, __end, __comp); + __elements_done += __n; #if _GLIBCXX_ASSERTIONS - __total_elements_done += __n; + __total_elements_done += __n; #endif - // Prefer own stack, small pieces. - if (__tl._M_leftover_parts.pop_front(__current)) - continue; + // Prefer own stack, small pieces. + if (__tl._M_leftover_parts.pop_front(__current)) + continue; -# pragma omp atomic - *__tl._M_elements_leftover -= __elements_done; +# pragma omp atomic + *__tl._M_elements_leftover -= __elements_done; - __elements_done = 0; + __elements_done = 0; #if _GLIBCXX_ASSERTIONS - double __search_start = omp_get_wtime(); + double __search_start = omp_get_wtime(); #endif - // Look for new work. - bool __successfully_stolen = false; - while (__wait && *__tl._M_elements_leftover > 0 - && !__successfully_stolen + // Look for new work. + bool __successfully_stolen = false; + while (__wait && *__tl._M_elements_leftover > 0 + && !__successfully_stolen #if _GLIBCXX_ASSERTIONS - // Possible dead-lock. - && (omp_get_wtime() < (__search_start + 1.0)) + // Possible dead-lock. + && (omp_get_wtime() < (__search_start + 1.0)) #endif - ) - { - _ThreadIndex __victim; - __victim = __rng(__num_threads); - - // Large pieces. - __successfully_stolen = (__victim != __iam) - && __tls[__victim]->_M_leftover_parts.pop_back(__current); - if (!__successfully_stolen) - __yield(); + ) + { + _ThreadIndex __victim; + __victim = __rng(__num_threads); + + // Large pieces. + __successfully_stolen = (__victim != __iam) + && __tls[__victim]->_M_leftover_parts.pop_back(__current); + if (!__successfully_stolen) + __yield(); #if !defined(__ICC) && !defined(__ECC) -# pragma omp flush +# pragma omp flush #endif - } + } #if _GLIBCXX_ASSERTIONS - if (omp_get_wtime() >= (__search_start + 1.0)) - { - sleep(1); - _GLIBCXX_PARALLEL_ASSERT(omp_get_wtime() - < (__search_start + 1.0)); - } + if (omp_get_wtime() >= (__search_start + 1.0)) + { + sleep(1); + _GLIBCXX_PARALLEL_ASSERT(omp_get_wtime() + < (__search_start + 1.0)); + } #endif - if (!__successfully_stolen) - { + if (!__successfully_stolen) + { #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(*__tl._M_elements_leftover == 0); + _GLIBCXX_PARALLEL_ASSERT(*__tl._M_elements_leftover == 0); #endif - return; - } - } - } - } - -/** @brief Top-level quicksort routine. - * @param __begin Begin iterator of sequence. - * @param __end End iterator of sequence. - * @param __comp Comparator. - * @param __num_threads Number of threads that are allowed to work on - * this part. - */ -template<typename _RAIter, typename _Compare> - void - __parallel_sort_qsb(_RAIter __begin, _RAIter __end, - _Compare __comp, - _ThreadIndex __num_threads) - { - _GLIBCXX_CALL(__end - __begin) - - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - typedef std::pair<_RAIter, _RAIter> _Piece; - - typedef _QSBThreadLocal<_RAIter> _TLSType; - - _DifferenceType __n = __end - __begin; - - if (__n <= 1) - return; - - // At least one element per processor. - if (__num_threads > __n) - __num_threads = static_cast<_ThreadIndex>(__n); - - // Initialize thread local storage - _TLSType** __tls = new _TLSType*[__num_threads]; - _DifferenceType __queue_size = - __num_threads * (_ThreadIndex)(log2(__n) + 1); - for (_ThreadIndex __t = 0; __t < __num_threads; ++__t) - __tls[__t] = new _QSBThreadLocal<_RAIter>(__queue_size); - - // There can never be more than ceil(log2(__n)) ranges on the stack, - // because - // 1. Only one processor pushes onto the stack - // 2. The largest range has at most length __n - // 3. Each range is larger than half of the range remaining - volatile _DifferenceType _M_elements_leftover = __n; - for (int __i = 0; __i < __num_threads; ++__i) - { - __tls[__i]->_M_elements_leftover = &_M_elements_leftover; - __tls[__i]->_M_num_threads = __num_threads; - __tls[__i]->_M_global = std::make_pair(__begin, __end); - - // Just in case nothing is left to assign. - __tls[__i]->_M_initial = std::make_pair(__end, __end); - } + return; + } + } + } + } - // Main recursion call. - __qsb_conquer( - __tls, __begin, __begin + __n, __comp, 0, __num_threads, true); + /** @brief Top-level quicksort routine. + * @param __begin Begin iterator of sequence. + * @param __end End iterator of sequence. + * @param __comp Comparator. + * @param __num_threads Number of threads that are allowed to work on + * this part. + */ + template<typename _RAIter, typename _Compare> + void + __parallel_sort_qsb(_RAIter __begin, _RAIter __end, + _Compare __comp, _ThreadIndex __num_threads) + { + _GLIBCXX_CALL(__end - __begin) + + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef std::pair<_RAIter, _RAIter> _Piece; + + typedef _QSBThreadLocal<_RAIter> _TLSType; + + _DifferenceType __n = __end - __begin; + + if (__n <= 1) + return; + + // At least one element per processor. + if (__num_threads > __n) + __num_threads = static_cast<_ThreadIndex>(__n); + + // Initialize thread local storage + _TLSType** __tls = new _TLSType*[__num_threads]; + _DifferenceType __queue_size = (__num_threads + * (_ThreadIndex)(__rd_log2(__n) + 1)); + for (_ThreadIndex __t = 0; __t < __num_threads; ++__t) + __tls[__t] = new _QSBThreadLocal<_RAIter>(__queue_size); + + // There can never be more than ceil(__rd_log2(__n)) ranges on the + // stack, because + // 1. Only one processor pushes onto the stack + // 2. The largest range has at most length __n + // 3. Each range is larger than half of the range remaining + volatile _DifferenceType __elements_leftover = __n; + for (int __i = 0; __i < __num_threads; ++__i) + { + __tls[__i]->_M_elements_leftover = &__elements_leftover; + __tls[__i]->_M_num_threads = __num_threads; + __tls[__i]->_M_global = std::make_pair(__begin, __end); + + // Just in case nothing is left to assign. + __tls[__i]->_M_initial = std::make_pair(__end, __end); + } + + // Main recursion call. + __qsb_conquer(__tls, __begin, __begin + __n, __comp, 0, + __num_threads, true); #if _GLIBCXX_ASSERTIONS - // All stack must be empty. - _Piece __dummy; - for (int __i = 1; __i < __num_threads; ++__i) - _GLIBCXX_PARALLEL_ASSERT( - !__tls[__i]->_M_leftover_parts.pop_back(__dummy)); + // All stack must be empty. + _Piece __dummy; + for (int __i = 1; __i < __num_threads; ++__i) + _GLIBCXX_PARALLEL_ASSERT( + !__tls[__i]->_M_leftover_parts.pop_back(__dummy)); #endif - for (int __i = 0; __i < __num_threads; ++__i) - delete __tls[__i]; - delete[] __tls; - } + for (int __i = 0; __i < __num_threads; ++__i) + delete __tls[__i]; + delete[] __tls; + } } // namespace __gnu_parallel #endif /* _GLIBCXX_PARALLEL_BALANCED_QUICKSORT_H */ diff --git a/libstdc++-v3/include/parallel/base.h b/libstdc++-v3/include/parallel/base.h index 6bdcedc206a..87d5752441a 100644 --- a/libstdc++-v3/include/parallel/base.h +++ b/libstdc++-v3/include/parallel/base.h @@ -93,13 +93,13 @@ namespace __gnu_parallel __is_parallel(const _Parallelism __p) { return __p != sequential; } -/** @brief Calculates the rounded-down logarithm of @__c __n for base 2. - * @param __n Argument. - * @return Returns 0 for any argument <1. - */ -template<typename _Size> - inline _Size - __rd_log2(_Size __n) + /** @brief Calculates the rounded-down logarithm of @c __n for base 2. + * @param __n Argument. + * @return Returns 0 for any argument <1. + */ + template<typename _Size> + inline _Size + __rd_log2(_Size __n) { _Size __k; for (__k = 0; __n > 1; __n >>= 1) @@ -107,356 +107,352 @@ template<typename _Size> return __k; } -/** @brief Encode two integers into one gnu_parallel::_CASable. - * @param __a First integer, to be encoded in the most-significant @__c - * _CASable_bits/2 bits. - * @param __b Second integer, to be encoded in the least-significant - * @__c _CASable_bits/2 bits. - * @return value encoding @__c __a and @__c __b. - * @see decode2 - */ -inline _CASable -__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> + /** @brief Encode two integers into one gnu_parallel::_CASable. + * @param __a First integer, to be encoded in the most-significant @c + * _CASable_bits/2 bits. + * @param __b Second integer, to be encoded in the least-significant + * @c _CASable_bits/2 bits. + * @return value encoding @c __a and @c __b. + * @see decode2 + */ + inline _CASable + __encode2(int __a, int __b) //must all be non-negative, actually { - private: - _Compare& _M_comp; + return (((_CASable)__a) << (_CASable_bits / 2)) | (((_CASable)__b) << 0); + } - public: - _EqualFromLess(_Compare& __comp) : _M_comp(__comp) { } + /** @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); + } - bool operator()(const _T1& __a, const _T2& __b) - { - return !_M_comp(__a, __b) && !_M_comp(__b, __a); - } - }; + //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 Similar to std::binder1st, - * but giving the argument types explicitly. */ -template<typename _Predicate, typename argument_type> - class __unary_negate - : public std::unary_function<argument_type, bool> - { - 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 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: + _Compare& _M_comp; -/** - * @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; } - }; + public: + _EqualFromLess(_Compare& __comp) : _M_comp(__comp) { } -/** @brief Similar to std::less, but allows two different types. */ -template<typename _T1, typename _T2> - 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; } - }; + bool operator()(const _T1& __a, const _T2& __b) + { return !_M_comp(__a, __b) && !_M_comp(__b, __a); } + }; - /** @brief Similar to std::plus, but allows two different types. */ -template<typename _Tp1, typename _Tp2> - struct _Plus : public std::binary_function<_Tp1, _Tp2, _Tp1> - { - typedef __typeof__(*static_cast<_Tp1*>(NULL) - + *static_cast<_Tp2*>(NULL)) __result; + /** @brief Similar to std::binder1st, + * but giving the argument types explicitly. */ + template<typename _Predicate, typename argument_type> + class __unary_negate + : public std::unary_function<argument_type, bool> + { + 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 - operator()(const _Tp1& __x, const _Tp2& __y) const - { return __x + __y; } - }; + /** @brief Similar to std::less, but allows two different types. */ + template<typename _T1, typename _T2> + 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 - operator()(const _Tp& __x, const _Tp& __y) const - { return __x + __y; } - }; + /** @brief Similar to std::plus, but allows two different types. */ + template<typename _Tp1, typename _Tp2> + 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. */ -template<typename _Tp1, typename _Tp2> - struct _Multiplies : public std::binary_function<_Tp1, _Tp2, _Tp1> - { - typedef __typeof__(*static_cast<_Tp1*>(NULL) - * *static_cast<_Tp2*>(NULL)) __result; + // 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 - operator()(const _Tp1& __x, const _Tp2& __y) const - { return __x * __y; } - }; + __result + operator()(const _Tp& __x, const _Tp& __y) const + { 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 - operator()(const _Tp& __x, const _Tp& __y) const - { return __x * __y; } - }; + /** @brief Similar to std::multiplies, but allows two different types. */ + template<typename _Tp1, typename _Tp2> + 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> - class _PseudoSequence; + // 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; -/** @brief _Iterator associated with __gnu_parallel::_PseudoSequence. - * If features the usual random-access iterator functionality. - * @param _Tp Sequence _M_value type. - * @param _DifferenceType Sequence difference type. - */ -template<typename _Tp, typename _DifferenceTp> - class _PseudoSequenceIterator - { - public: - typedef _DifferenceTp _DifferenceType; + __result + operator()(const _Tp& __x, const _Tp& __y) const + { return __x * __y; } + }; - private: - const _Tp& _M_val; - _DifferenceType _M_pos; - public: - _PseudoSequenceIterator(const _Tp& _M_val, _DifferenceType _M_pos) - : _M_val(_M_val), _M_pos(_M_pos) { } + template<typename _Tp, typename _DifferenceTp> + class _PseudoSequence; - // Pre-increment operator. - _PseudoSequenceIterator& - operator++() + /** @brief _Iterator associated with __gnu_parallel::_PseudoSequence. + * If features the usual random-access iterator functionality. + * @param _Tp Sequence _M_value type. + * @param _DifferenceType Sequence difference type. + */ + template<typename _Tp, typename _DifferenceTp> + class _PseudoSequenceIterator { - ++_M_pos; - return *this; - } + public: + typedef _DifferenceTp _DifferenceType; - // Post-increment operator. - const _PseudoSequenceIterator - operator++(int) - { return _PseudoSequenceIterator(_M_pos++); } + private: + const _Tp& _M_val; + _DifferenceType _M_pos; - const _Tp& - operator*() const - { return _M_val; } + public: + _PseudoSequenceIterator(const _Tp& __val, _DifferenceType __pos) + : _M_val(__val), _M_pos(__pos) { } - 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. - */ -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; + // Pre-increment operator. + _PseudoSequenceIterator& + operator++() + { + ++_M_pos; + return *this; + } - /** @brief Constructor. - * @param _M_val Element of the sequence. - * @param __count Number of (virtual) copies. + // Post-increment operator. + const _PseudoSequenceIterator + 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) - : _M_val(_M_val), __count(__count) { } - - /** @brief Begin iterator. */ - iterator - begin() const - { return iterator(_M_val, 0); } - - /** @brief End iterator. */ - iterator - end() const - { return iterator(_M_val, __count); } - - private: - const _Tp& _M_val; - _DifferenceType __count; - }; - -/** @brief Functor that does nothing */ -template<typename _ValueTp> - class _VoidFunctor - { - inline void - operator()(const _ValueTp& __v) const { } - }; - -/** @brief Compute the median of three referenced elements, - 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; + 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. + * @param _M_val Element of the sequence. + * @param __count Number of (virtual) copies. + */ + _PseudoSequence(const _Tp& __val, _DifferenceType __count) + : _M_val(__val), _M_count(__count) { } + + /** @brief Begin iterator. */ + iterator + begin() const + { return iterator(_M_val, 0); } + + /** @brief End iterator. */ + iterator + end() const + { return iterator(_M_val, _M_count); } + + private: + const _Tp& _M_val; + _DifferenceType _M_count; + }; + + /** @brief Functor that does nothing */ + template<typename _ValueTp> + class _VoidFunctor + { + inline void + operator()(const _ValueTp& __v) const { } + }; + + /** @brief Compute the median of three referenced elements, + 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 - if (__comp(*__a, *__c)) - return __c; - else - return __a; - else - { - // Just swap __a and __b. - if (__comp(*__a, *__c)) - return __a; - else - if (__comp(*__b, *__c)) - return __c; - else - return __b; - } - } + { + // Just swap __a and __b. + if (__comp(*__a, *__c)) + return __a; + else + if (__comp(*__b, *__c)) + return __c; + else + return __b; + } + } #define _GLIBCXX_PARALLEL_ASSERT(_Condition) __glibcxx_assert(_Condition) diff --git a/libstdc++-v3/include/parallel/checkers.h b/libstdc++-v3/include/parallel/checkers.h index 70cc949e3fe..2a977acedf4 100644 --- a/libstdc++-v3/include/parallel/checkers.h +++ b/libstdc++-v3/include/parallel/checkers.h @@ -39,12 +39,12 @@ namespace __gnu_parallel { /** - * @brief Check whether @__c [__begin, @__c __end) is sorted according - * to @__c __comp. + * @brief Check whether @c [__begin, @c __end) is sorted according + * to @c __comp. * @param __begin Begin iterator of sequence. * @param __end End iterator of sequence. * @param __comp Comparator. - * @return @__c true if sorted, @__c false otherwise. + * @return @c true if sorted, @c false otherwise. */ template<typename _IIter, typename _Compare> bool @@ -68,5 +68,6 @@ namespace __gnu_parallel return true; } +} #endif /* _GLIBCXX_PARALLEL_CHECKERS_H */ diff --git a/libstdc++-v3/include/parallel/compatibility.h b/libstdc++-v3/include/parallel/compatibility.h index c4f691e5b77..688a7cf348f 100644 --- a/libstdc++-v3/include/parallel/compatibility.h +++ b/libstdc++-v3/include/parallel/compatibility.h @@ -227,8 +227,8 @@ namespace __gnu_parallel #endif - /** @brief Compare @__c *__ptr and @__c __comparand. If equal, let @__c - * *__ptr=__replacement and return @__c true, return @__c false otherwise. + /** @brief Compare @c *__ptr and @c __comparand. If equal, let @c + * *__ptr=__replacement and return @c true, return @c false otherwise. * * Implementation is heavily platform-dependent. * @param __ptr Pointer to 32-bit signed integer. @@ -270,8 +270,8 @@ namespace __gnu_parallel #endif } - /** @brief Compare @__c *__ptr and @__c __comparand. If equal, let @__c - * *__ptr=__replacement and return @__c true, return @__c false otherwise. + /** @brief Compare @c *__ptr and @c __comparand. If equal, let @c + * *__ptr=__replacement and return @c true, return @c false otherwise. * * Implementation is heavily platform-dependent. * @param __ptr Pointer to 64-bit signed integer. @@ -323,8 +323,8 @@ namespace __gnu_parallel #endif } - /** @brief Compare @__c *__ptr and @__c __comparand. If equal, let @__c - * *__ptr=__replacement and return @__c true, return @__c false otherwise. + /** @brief Compare @c *__ptr and @c __comparand. If equal, let @c + * *__ptr=__replacement and return @c true, return @c false otherwise. * * Implementation is heavily platform-dependent. * @param __ptr Pointer to signed integer. diff --git a/libstdc++-v3/include/parallel/equally_split.h b/libstdc++-v3/include/parallel/equally_split.h index 31ed87d16f3..481c9886840 100644 --- a/libstdc++-v3/include/parallel/equally_split.h +++ b/libstdc++-v3/include/parallel/equally_split.h @@ -1,6 +1,6 @@ // -*- C++ -*- -// Copyright (C) 2007, 2009 Free Software Foundation, Inc. +// Copyright (C) 2007, 2008, 2009 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 @@ -33,57 +33,56 @@ namespace __gnu_parallel { -/** @brief function to split a sequence into parts of almost equal size. - * - * The resulting sequence __s of length __num_threads+1 contains the splitting - * positions when splitting the range [0,__n) into parts of almost - * equal size (plus minus 1). The first entry is 0, the last one -* n. There may result empty parts. - * @param __n Number of elements - * @param __num_threads Number of parts - * @param __s Splitters - * @returns End of __splitter sequence, i.e. @__c __s+__num_threads+1 */ -template<typename _DifferenceType, typename _OutputIterator> - _OutputIterator - equally_split(_DifferenceType __n, _ThreadIndex __num_threads, - _OutputIterator __s) - { - _DifferenceType __chunk_length = __n / __num_threads; - _DifferenceType __num_longer_chunks = __n % __num_threads; - _DifferenceType __pos = 0; - for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) - { - *__s++ = __pos; - __pos += (__i < __num_longer_chunks) ? - (__chunk_length + 1) : __chunk_length; - } - *__s++ = __n; - return __s; - } + /** @brief function to split a sequence into parts of almost equal size. + * + * The resulting sequence __s of length __num_threads+1 contains the + * splitting positions when splitting the range [0,__n) into parts of + * almost equal size (plus minus 1). The first entry is 0, the last + * one n. There may result empty parts. + * @param __n Number of elements + * @param __num_threads Number of parts + * @param __s Splitters + * @returns End of __splitter sequence, i.e. @c __s+__num_threads+1 */ + template<typename _DifferenceType, typename _OutputIterator> + _OutputIterator + equally_split(_DifferenceType __n, _ThreadIndex __num_threads, + _OutputIterator __s) + { + _DifferenceType __chunk_length = __n / __num_threads; + _DifferenceType __num_longer_chunks = __n % __num_threads; + _DifferenceType __pos = 0; + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + { + *__s++ = __pos; + __pos += ((__i < __num_longer_chunks) + ? (__chunk_length + 1) : __chunk_length); + } + *__s++ = __n; + return __s; + } - -/** @brief function to split a sequence into parts of almost equal size. - * - * Returns the position of the splitting point between - * thread number __thread_no (included) and - * thread number __thread_no+1 (excluded). - * @param __n Number of elements - * @param __num_threads Number of parts - * @returns splitting point */ -template<typename _DifferenceType> - _DifferenceType - equally_split_point(_DifferenceType __n, - _ThreadIndex __num_threads, - _ThreadIndex __thread_no) - { - _DifferenceType __chunk_length = __n / __num_threads; - _DifferenceType __num_longer_chunks = __n % __num_threads; - if (__thread_no < __num_longer_chunks) - return __thread_no * (__chunk_length + 1); - else - return __num_longer_chunks * (__chunk_length + 1) + /** @brief function to split a sequence into parts of almost equal size. + * + * Returns the position of the splitting point between + * thread number __thread_no (included) and + * thread number __thread_no+1 (excluded). + * @param __n Number of elements + * @param __num_threads Number of parts + * @returns splitting point */ + template<typename _DifferenceType> + _DifferenceType + equally_split_point(_DifferenceType __n, + _ThreadIndex __num_threads, + _ThreadIndex __thread_no) + { + _DifferenceType __chunk_length = __n / __num_threads; + _DifferenceType __num_longer_chunks = __n % __num_threads; + if (__thread_no < __num_longer_chunks) + return __thread_no * (__chunk_length + 1); + else + return __num_longer_chunks * (__chunk_length + 1) + (__thread_no - __num_longer_chunks) * __chunk_length; - } + } } #endif /* _GLIBCXX_PARALLEL_EQUALLY_SPLIT_H */ diff --git a/libstdc++-v3/include/parallel/find.h b/libstdc++-v3/include/parallel/find.h index 050a80d8af0..b4e581488ae 100644 --- a/libstdc++-v3/include/parallel/find.h +++ b/libstdc++-v3/include/parallel/find.h @@ -42,360 +42,363 @@ namespace __gnu_parallel { -/** - * @brief Parallel std::find, switch for different algorithms. - * @param __begin1 Begin iterator of first sequence. - * @param __end1 End iterator of first sequence. - * @param __begin2 Begin iterator of second sequence. Must have same - * length as first sequence. - * @param __pred Find predicate. - * @param __selector _Functionality (e. g. std::find_if (), std::equal(),...) - * @return Place of finding in both sequences. - */ -template<typename _RAIter1, - typename _RAIter2, - typename _Pred, - typename _Selector> - inline std::pair<_RAIter1, _RAIter2> - __find_template(_RAIter1 __begin1, _RAIter1 __end1, - _RAIter2 __begin2, _Pred __pred, _Selector __selector) - { - switch (_Settings::get().find_algorithm) - { - case GROWING_BLOCKS: - return __find_template(__begin1, __end1, __begin2, __pred, __selector, - growing_blocks_tag()); - case CONSTANT_SIZE_BLOCKS: - return __find_template(__begin1, __end1, __begin2, __pred, __selector, - constant_size_blocks_tag()); - case EQUAL_SPLIT: - return __find_template(__begin1, __end1, __begin2, __pred, __selector, - equal_split_tag()); - default: - _GLIBCXX_PARALLEL_ASSERT(false); - return std::make_pair(__begin1, __begin2); - } - } + /** + * @brief Parallel std::find, switch for different algorithms. + * @param __begin1 Begin iterator of first sequence. + * @param __end1 End iterator of first sequence. + * @param __begin2 Begin iterator of second sequence. Must have same + * length as first sequence. + * @param __pred Find predicate. + * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) + * @return Place of finding in both sequences. + */ + template<typename _RAIter1, + typename _RAIter2, + typename _Pred, + typename _Selector> + inline std::pair<_RAIter1, _RAIter2> + __find_template(_RAIter1 __begin1, _RAIter1 __end1, + _RAIter2 __begin2, _Pred __pred, _Selector __selector) + { + switch (_Settings::get().find_algorithm) + { + case GROWING_BLOCKS: + return __find_template(__begin1, __end1, __begin2, __pred, + __selector, growing_blocks_tag()); + case CONSTANT_SIZE_BLOCKS: + return __find_template(__begin1, __end1, __begin2, __pred, + __selector, constant_size_blocks_tag()); + case EQUAL_SPLIT: + return __find_template(__begin1, __end1, __begin2, __pred, + __selector, equal_split_tag()); + default: + _GLIBCXX_PARALLEL_ASSERT(false); + return std::make_pair(__begin1, __begin2); + } + } #if _GLIBCXX_FIND_EQUAL_SPLIT -/** - * @brief Parallel std::find, equal splitting variant. - * @param __begin1 Begin iterator of first sequence. - * @param __end1 End iterator of first sequence. - * @param __begin2 Begin iterator of second sequence. Second __sequence - * must have same length as first sequence. - * @param __pred Find predicate. - * @param __selector _Functionality (e. g. std::find_if (), std::equal(),...) - * @return Place of finding in both sequences. - */ -template<typename _RAIter1, - typename _RAIter2, - typename _Pred, - typename _Selector> - std::pair<_RAIter1, _RAIter2> - __find_template(_RAIter1 __begin1, - _RAIter1 __end1, - _RAIter2 __begin2, - _Pred __pred, - _Selector __selector, - equal_split_tag) - { - _GLIBCXX_CALL(__end1 - __begin1) - - typedef std::iterator_traits<_RAIter1> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; - typedef typename _TraitsType::value_type _ValueType; - - _DifferenceType __length = __end1 - __begin1; - _DifferenceType __result = __length; - _DifferenceType* __borders; - - omp_lock_t __result_lock; - omp_init_lock(&__result_lock); - - _ThreadIndex __num_threads = __get_max_threads(); -# pragma omp parallel num_threads(__num_threads) + /** + * @brief Parallel std::find, equal splitting variant. + * @param __begin1 Begin iterator of first sequence. + * @param __end1 End iterator of first sequence. + * @param __begin2 Begin iterator of second sequence. Second __sequence + * must have same length as first sequence. + * @param __pred Find predicate. + * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) + * @return Place of finding in both sequences. + */ + template<typename _RAIter1, + typename _RAIter2, + typename _Pred, + typename _Selector> + std::pair<_RAIter1, _RAIter2> + __find_template(_RAIter1 __begin1, _RAIter1 __end1, + _RAIter2 __begin2, _Pred __pred, + _Selector __selector, equal_split_tag) + { + _GLIBCXX_CALL(__end1 - __begin1) + + typedef std::iterator_traits<_RAIter1> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef typename _TraitsType::value_type _ValueType; + + _DifferenceType __length = __end1 - __begin1; + _DifferenceType __result = __length; + _DifferenceType* __borders; + + omp_lock_t __result_lock; + omp_init_lock(&__result_lock); + + _ThreadIndex __num_threads = __get_max_threads(); +# pragma omp parallel num_threads(__num_threads) { -# pragma omp single - { - __num_threads = omp_get_num_threads(); - __borders = new _DifferenceType[__num_threads + 1]; - equally_split(__length, __num_threads, __borders); - } //single - - _ThreadIndex __iam = omp_get_thread_num(); - _DifferenceType __start = __borders[__iam], - __stop = __borders[__iam + 1]; - - _RAIter1 __i1 = __begin1 + __start; - _RAIter2 __i2 = __begin2 + __start; - for (_DifferenceType __pos = __start; __pos < __stop; ++__pos) - { - #pragma omp flush(__result) - // Result has been set to something lower. - if (__result < __pos) - break; - - if (__selector(__i1, __i2, __pred)) - { - omp_set_lock(&__result_lock); - if (__pos < __result) - __result = __pos; - omp_unset_lock(&__result_lock); - break; - } - ++__i1; - ++__i2; - } +# pragma omp single + { + __num_threads = omp_get_num_threads(); + __borders = new _DifferenceType[__num_threads + 1]; + equally_split(__length, __num_threads, __borders); + } //single + + _ThreadIndex __iam = omp_get_thread_num(); + _DifferenceType __start = __borders[__iam], + __stop = __borders[__iam + 1]; + + _RAIter1 __i1 = __begin1 + __start; + _RAIter2 __i2 = __begin2 + __start; + for (_DifferenceType __pos = __start; __pos < __stop; ++__pos) + { +# pragma omp flush(__result) + // Result has been set to something lower. + if (__result < __pos) + break; + + if (__selector(__i1, __i2, __pred)) + { + omp_set_lock(&__result_lock); + if (__pos < __result) + __result = __pos; + omp_unset_lock(&__result_lock); + break; + } + ++__i1; + ++__i2; + } } //parallel - omp_destroy_lock(&__result_lock); - delete[] __borders; + omp_destroy_lock(&__result_lock); + delete[] __borders; - return - std::pair<_RAIter1, _RAIter2>(__begin1 + __result, __begin2 + __result); - } + return std::pair<_RAIter1, _RAIter2>(__begin1 + __result, + __begin2 + __result); + } #endif #if _GLIBCXX_FIND_GROWING_BLOCKS -/** - * @brief Parallel std::find, growing block size variant. - * @param __begin1 Begin iterator of first sequence. - * @param __end1 End iterator of first sequence. - * @param __begin2 Begin iterator of second sequence. Second __sequence - * must have same length as first sequence. - * @param __pred Find predicate. - * @param __selector _Functionality (e. g. std::find_if (), std::equal(),...) - * @return Place of finding in both sequences. - * @see __gnu_parallel::_Settings::find_sequential_search_size - * @see __gnu_parallel::_Settings::find_initial_block_size - * @see __gnu_parallel::_Settings::find_maximum_block_size - * @see __gnu_parallel::_Settings::find_increasing_factor - * - * There are two main differences between the growing blocks and - * the constant-size blocks variants. - * 1. For GB, the block size grows; for CSB, the block size is fixed. - * 2. For GB, the blocks are allocated dynamically; - * for CSB, the blocks are allocated in a predetermined manner, - * namely spacial round-robin. - */ -template<typename _RAIter1, - typename _RAIter2, - typename _Pred, - typename _Selector> - std::pair<_RAIter1, _RAIter2> - __find_template(_RAIter1 __begin1, _RAIter1 __end1, - _RAIter2 __begin2, _Pred __pred, _Selector __selector, - growing_blocks_tag) - { - _GLIBCXX_CALL(__end1 - __begin1) - - typedef std::iterator_traits<_RAIter1> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; - typedef typename _TraitsType::value_type _ValueType; - - const _Settings& __s = _Settings::get(); - - _DifferenceType __length = __end1 - __begin1; - - _DifferenceType __sequential_search_size = - std::min<_DifferenceType>(__length, __s.find_sequential_search_size); - - // Try it sequentially first. - std::pair<_RAIter1, _RAIter2> __find_seq_result = - __selector._M_sequential_algorithm( - __begin1, __begin1 + __sequential_search_size, __begin2, __pred); - - if (__find_seq_result.first != (__begin1 + __sequential_search_size)) - return __find_seq_result; - - // Index of beginning of next free block (after sequential find). - _DifferenceType __next_block_start = __sequential_search_size; - _DifferenceType __result = __length; - - omp_lock_t __result_lock; - omp_init_lock(&__result_lock); - - _ThreadIndex __num_threads = __get_max_threads(); -# pragma omp parallel shared(__result) num_threads(__num_threads) + /** + * @brief Parallel std::find, growing block size variant. + * @param __begin1 Begin iterator of first sequence. + * @param __end1 End iterator of first sequence. + * @param __begin2 Begin iterator of second sequence. Second __sequence + * must have same length as first sequence. + * @param __pred Find predicate. + * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) + * @return Place of finding in both sequences. + * @see __gnu_parallel::_Settings::find_sequential_search_size + * @see __gnu_parallel::_Settings::find_initial_block_size + * @see __gnu_parallel::_Settings::find_maximum_block_size + * @see __gnu_parallel::_Settings::find_increasing_factor + * + * There are two main differences between the growing blocks and + * the constant-size blocks variants. + * 1. For GB, the block size grows; for CSB, the block size is fixed. + * 2. For GB, the blocks are allocated dynamically; + * for CSB, the blocks are allocated in a predetermined manner, + * namely spacial round-robin. + */ + template<typename _RAIter1, + typename _RAIter2, + typename _Pred, + typename _Selector> + std::pair<_RAIter1, _RAIter2> + __find_template(_RAIter1 __begin1, _RAIter1 __end1, + _RAIter2 __begin2, _Pred __pred, _Selector __selector, + growing_blocks_tag) + { + _GLIBCXX_CALL(__end1 - __begin1) + + typedef std::iterator_traits<_RAIter1> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef typename _TraitsType::value_type _ValueType; + + const _Settings& __s = _Settings::get(); + + _DifferenceType __length = __end1 - __begin1; + + _DifferenceType + __sequential_search_size = std::min<_DifferenceType> + (__length, __s.find_sequential_search_size); + + // Try it sequentially first. + std::pair<_RAIter1, _RAIter2> + __find_seq_result = __selector._M_sequential_algorithm + (__begin1, __begin1 + __sequential_search_size, + __begin2, __pred); + + if (__find_seq_result.first != (__begin1 + __sequential_search_size)) + return __find_seq_result; + + // Index of beginning of next free block (after sequential find). + _DifferenceType __next_block_start = __sequential_search_size; + _DifferenceType __result = __length; + + omp_lock_t __result_lock; + omp_init_lock(&__result_lock); + + _ThreadIndex __num_threads = __get_max_threads(); +# pragma omp parallel shared(__result) num_threads(__num_threads) { # pragma omp single - __num_threads = omp_get_num_threads(); + __num_threads = omp_get_num_threads(); - // Not within first __k elements -> start parallel. - _ThreadIndex __iam = omp_get_thread_num(); + // Not within first __k elements -> start parallel. + _ThreadIndex __iam = omp_get_thread_num(); - _DifferenceType __block_size = __s.find_initial_block_size; - _DifferenceType __start = - __fetch_and_add<_DifferenceType>(&__next_block_start, __block_size); + _DifferenceType __block_size = __s.find_initial_block_size; + _DifferenceType __start = __fetch_and_add<_DifferenceType> + (&__next_block_start, __block_size); - // Get new block, update pointer to next block. - _DifferenceType __stop = - std::min<_DifferenceType>(__length, __start + __block_size); + // Get new block, update pointer to next block. + _DifferenceType __stop = + std::min<_DifferenceType>(__length, __start + __block_size); - std::pair<_RAIter1, _RAIter2> __local_result; + std::pair<_RAIter1, _RAIter2> __local_result; - while (__start < __length) - { + while (__start < __length) + { # pragma omp flush(__result) - // Get new value of result. - if (__result < __start) - { - // No chance to find first element. - break; - } - - __local_result = __selector._M_sequential_algorithm( - __begin1 + __start, __begin1 + __stop, - __begin2 + __start, __pred); - if (__local_result.first != (__begin1 + __stop)) - { - omp_set_lock(&__result_lock); - if ((__local_result.first - __begin1) < __result) - { - __result = __local_result.first - __begin1; - - // Result cannot be in future blocks, stop algorithm. - __fetch_and_add<_DifferenceType>( - &__next_block_start, __length); - } - omp_unset_lock(&__result_lock); - } - - __block_size = std::min<_DifferenceType>( - __block_size * __s.find_increasing_factor, - __s.find_maximum_block_size); - - // Get new block, update pointer to next block. - __start = - __fetch_and_add<_DifferenceType>( - &__next_block_start, __block_size); - __stop = ((__length < (__start + __block_size)) - ? __length : (__start + __block_size)); - } + // Get new value of result. + if (__result < __start) + { + // No chance to find first element. + break; + } + + __local_result = __selector._M_sequential_algorithm + (__begin1 + __start, __begin1 + __stop, + __begin2 + __start, __pred); + + if (__local_result.first != (__begin1 + __stop)) + { + omp_set_lock(&__result_lock); + if ((__local_result.first - __begin1) < __result) + { + __result = __local_result.first - __begin1; + + // Result cannot be in future blocks, stop algorithm. + __fetch_and_add<_DifferenceType>(&__next_block_start, + __length); + } + omp_unset_lock(&__result_lock); + } + + __block_size = std::min<_DifferenceType> + (__block_size * __s.find_increasing_factor, + __s.find_maximum_block_size); + + // Get new block, update pointer to next block. + __start = __fetch_and_add<_DifferenceType>(&__next_block_start, + __block_size); + __stop = (__length < (__start + __block_size) + ? __length : (__start + __block_size)); + } } //parallel - omp_destroy_lock(&__result_lock); + omp_destroy_lock(&__result_lock); - // Return iterator on found element. - return - std::pair<_RAIter1, _RAIter2>(__begin1 + __result, __begin2 + __result); - } + // Return iterator on found element. + return + std::pair<_RAIter1, _RAIter2>(__begin1 + __result, + __begin2 + __result); + } #endif #if _GLIBCXX_FIND_CONSTANT_SIZE_BLOCKS -/** - * @brief Parallel std::find, constant block size variant. - * @param __begin1 Begin iterator of first sequence. - * @param __end1 End iterator of first sequence. - * @param __begin2 Begin iterator of second sequence. Second __sequence - * must have same length as first sequence. - * @param __pred Find predicate. - * @param __selector _Functionality (e. g. std::find_if (), std::equal(),...) - * @return Place of finding in both sequences. - * @see __gnu_parallel::_Settings::find_sequential_search_size - * @see __gnu_parallel::_Settings::find_block_size - * There are two main differences between the growing blocks and the - * constant-size blocks variants. - * 1. For GB, the block size grows; for CSB, the block size is fixed. - * 2. For GB, the blocks are allocated dynamically; for CSB, the - * blocks are allocated in a predetermined manner, namely spacial - * round-robin. - */ -template<typename _RAIter1, - typename _RAIter2, - typename _Pred, - typename _Selector> - std::pair<_RAIter1, _RAIter2> - __find_template(_RAIter1 __begin1, _RAIter1 __end1, - _RAIter2 __begin2, _Pred __pred, _Selector __selector, - constant_size_blocks_tag) - { - _GLIBCXX_CALL(__end1 - __begin1) - typedef std::iterator_traits<_RAIter1> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; - typedef typename _TraitsType::value_type _ValueType; - - const _Settings& __s = _Settings::get(); - - _DifferenceType __length = __end1 - __begin1; - - _DifferenceType __sequential_search_size = std::min<_DifferenceType>( - __length, __s.find_sequential_search_size); - - // Try it sequentially first. - std::pair<_RAIter1, _RAIter2> __find_seq_result = - __selector._M_sequential_algorithm( - __begin1, __begin1 + __sequential_search_size, __begin2, __pred); - - if (__find_seq_result.first != (__begin1 + __sequential_search_size)) - return __find_seq_result; - - _DifferenceType __result = __length; - omp_lock_t __result_lock; - omp_init_lock(&__result_lock); - - // Not within first __sequential_search_size elements -> start parallel. - - _ThreadIndex __num_threads = __get_max_threads(); -# pragma omp parallel shared(__result) num_threads(__num_threads) + /** + * @brief Parallel std::find, constant block size variant. + * @param __begin1 Begin iterator of first sequence. + * @param __end1 End iterator of first sequence. + * @param __begin2 Begin iterator of second sequence. Second __sequence + * must have same length as first sequence. + * @param __pred Find predicate. + * @param __selector _Functionality (e. g. std::find_if(), std::equal(),...) + * @return Place of finding in both sequences. + * @see __gnu_parallel::_Settings::find_sequential_search_size + * @see __gnu_parallel::_Settings::find_block_size + * There are two main differences between the growing blocks and the + * constant-size blocks variants. + * 1. For GB, the block size grows; for CSB, the block size is fixed. + * 2. For GB, the blocks are allocated dynamically; for CSB, the + * blocks are allocated in a predetermined manner, namely spacial + * round-robin. + */ + template<typename _RAIter1, + typename _RAIter2, + typename _Pred, + typename _Selector> + std::pair<_RAIter1, _RAIter2> + __find_template(_RAIter1 __begin1, _RAIter1 __end1, + _RAIter2 __begin2, _Pred __pred, _Selector __selector, + constant_size_blocks_tag) + { + _GLIBCXX_CALL(__end1 - __begin1) + typedef std::iterator_traits<_RAIter1> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef typename _TraitsType::value_type _ValueType; + + const _Settings& __s = _Settings::get(); + + _DifferenceType __length = __end1 - __begin1; + + _DifferenceType __sequential_search_size = std::min<_DifferenceType> + (__length, __s.find_sequential_search_size); + + // Try it sequentially first. + std::pair<_RAIter1, _RAIter2> + __find_seq_result = __selector._M_sequential_algorithm + (__begin1, __begin1 + __sequential_search_size, __begin2, __pred); + + if (__find_seq_result.first != (__begin1 + __sequential_search_size)) + return __find_seq_result; + + _DifferenceType __result = __length; + omp_lock_t __result_lock; + omp_init_lock(&__result_lock); + + // Not within first __sequential_search_size elements -> start parallel. + + _ThreadIndex __num_threads = __get_max_threads(); +# pragma omp parallel shared(__result) num_threads(__num_threads) { # pragma omp single - __num_threads = omp_get_num_threads(); + __num_threads = omp_get_num_threads(); - _ThreadIndex __iam = omp_get_thread_num(); - _DifferenceType __block_size = __s.find_initial_block_size; + _ThreadIndex __iam = omp_get_thread_num(); + _DifferenceType __block_size = __s.find_initial_block_size; - // First element of thread's current iteration. - _DifferenceType __iteration_start = __sequential_search_size; + // First element of thread's current iteration. + _DifferenceType __iteration_start = __sequential_search_size; - // Where to work (initialization). - _DifferenceType __start = __iteration_start + __iam * __block_size; - _DifferenceType __stop = - std::min<_DifferenceType>(__length, __start + __block_size); + // Where to work (initialization). + _DifferenceType __start = __iteration_start + __iam * __block_size; + _DifferenceType __stop = std::min<_DifferenceType>(__length, + __start + + __block_size); - std::pair<_RAIter1, _RAIter2> __local_result; + std::pair<_RAIter1, _RAIter2> __local_result; - while (__start < __length) - { - // Get new value of result. + while (__start < __length) + { + // Get new value of result. # pragma omp flush(__result) - // No chance to find first element. - if (__result < __start) - break; - __local_result = __selector._M_sequential_algorithm( - __begin1 + __start, __begin1 + __stop, - __begin2 + __start, __pred); - if (__local_result.first != (__begin1 + __stop)) - { - omp_set_lock(&__result_lock); - if ((__local_result.first - __begin1) < __result) - __result = __local_result.first - __begin1; - omp_unset_lock(&__result_lock); - // Will not find better value in its interval. - break; - } - - __iteration_start += __num_threads * __block_size; - - // Where to work. - __start = __iteration_start + __iam * __block_size; - __stop = std::min<_DifferenceType>( - __length, __start + __block_size); - } + // No chance to find first element. + if (__result < __start) + break; + + __local_result = __selector._M_sequential_algorithm + (__begin1 + __start, __begin1 + __stop, + __begin2 + __start, __pred); + + if (__local_result.first != (__begin1 + __stop)) + { + omp_set_lock(&__result_lock); + if ((__local_result.first - __begin1) < __result) + __result = __local_result.first - __begin1; + omp_unset_lock(&__result_lock); + // Will not find better value in its interval. + break; + } + + __iteration_start += __num_threads * __block_size; + + // Where to work. + __start = __iteration_start + __iam * __block_size; + __stop = std::min<_DifferenceType>(__length, + __start + __block_size); + } } //parallel - omp_destroy_lock(&__result_lock); + omp_destroy_lock(&__result_lock); - // Return iterator on found element. - return - std::pair<_RAIter1, _RAIter2>(__begin1 + __result, __begin2 + __result); - } + // Return iterator on found element. + return std::pair<_RAIter1, _RAIter2>(__begin1 + __result, + __begin2 + __result); + } #endif } // end namespace diff --git a/libstdc++-v3/include/parallel/find_selectors.h b/libstdc++-v3/include/parallel/find_selectors.h index 0d385bc6c94..df77978a9dd 100644 --- a/libstdc++-v3/include/parallel/find_selectors.h +++ b/libstdc++-v3/include/parallel/find_selectors.h @@ -103,12 +103,12 @@ namespace __gnu_parallel typename _Pred> std::pair<_RAIter1, _RAIter2> _M_sequential_algorithm(_RAIter1 __begin1, - _RAIter1 __end1, - _RAIter2 __begin2, _Pred __pred) + _RAIter1 __end1, + _RAIter2 __begin2, _Pred __pred) { // Passed end iterator is one short. _RAIter1 __spot = adjacent_find(__begin1, __end1 + 1, - __pred, sequential_tag()); + __pred, sequential_tag()); if (__spot == (__end1 + 1)) __spot = __end1; return std::make_pair(__spot, __begin2); @@ -141,56 +141,57 @@ namespace __gnu_parallel typename _Pred> std::pair<_RAIter1, _RAIter2> _M_sequential_algorithm(_RAIter1 __begin1, - _RAIter1 __end1, - _RAIter2 __begin2, _Pred __pred) - { return mismatch(__begin1, __end1, __begin2, __pred, sequential_tag()); - } + _RAIter1 __end1, + _RAIter2 __begin2, _Pred __pred) + { return mismatch(__begin1, __end1, __begin2, + __pred, sequential_tag()); } }; /** @brief Test predicate on several elements. */ template<typename _FIterator> - struct __find_first_of_selector : public __generic_find_selector - { - _FIterator _M_begin; - _FIterator _M_end; - - explicit __find_first_of_selector(_FIterator __begin, _FIterator __end) - : _M_begin(__begin), _M_end(__end) { } - - /** @brief Test on one position. - * @param __i1 _Iterator on first sequence. - * @param __i2 _Iterator on second sequence (unused). - * @param __pred Find predicate. */ - template<typename _RAIter1, typename _RAIter2, - typename _Pred> - bool - operator()(_RAIter1 __i1, _RAIter2 __i2, _Pred __pred) - { - for (_FIterator __pos_in_candidates = _M_begin; - __pos_in_candidates != _M_end; ++__pos_in_candidates) - if (__pred(*__i1, *__pos_in_candidates)) - return true; - return false; - } - - /** @brief Corresponding sequential algorithm on a sequence. - * @param __begin1 Begin iterator of first sequence. - * @param __end1 End iterator of first sequence. - * @param __begin2 Begin iterator of second sequence. - * @param __pred Find predicate. */ - template<typename _RAIter1, typename _RAIter2, - typename _Pred> - std::pair<_RAIter1, _RAIter2> - _M_sequential_algorithm(_RAIter1 __begin1, - _RAIter1 __end1, - _RAIter2 __begin2, _Pred __pred) - { - return std::make_pair( - find_first_of(__begin1, __end1, _M_begin, _M_end, __pred, - sequential_tag()), __begin2); - } - }; + struct __find_first_of_selector : public __generic_find_selector + { + _FIterator _M_begin; + _FIterator _M_end; + + explicit __find_first_of_selector(_FIterator __begin, + _FIterator __end) + : _M_begin(__begin), _M_end(__end) { } + + /** @brief Test on one position. + * @param __i1 _Iterator on first sequence. + * @param __i2 _Iterator on second sequence (unused). + * @param __pred Find predicate. */ + template<typename _RAIter1, typename _RAIter2, + typename _Pred> + bool + operator()(_RAIter1 __i1, _RAIter2 __i2, _Pred __pred) + { + for (_FIterator __pos_in_candidates = _M_begin; + __pos_in_candidates != _M_end; ++__pos_in_candidates) + if (__pred(*__i1, *__pos_in_candidates)) + return true; + return false; + } + + /** @brief Corresponding sequential algorithm on a sequence. + * @param __begin1 Begin iterator of first sequence. + * @param __end1 End iterator of first sequence. + * @param __begin2 Begin iterator of second sequence. + * @param __pred Find predicate. */ + template<typename _RAIter1, typename _RAIter2, + typename _Pred> + std::pair<_RAIter1, _RAIter2> + _M_sequential_algorithm(_RAIter1 __begin1, + _RAIter1 __end1, + _RAIter2 __begin2, _Pred __pred) + { + return std::make_pair(find_first_of(__begin1, __end1, + _M_begin, _M_end, __pred, + sequential_tag()), __begin2); + } + }; } #endif /* _GLIBCXX_PARALLEL_FIND_SELECTORS_H */ diff --git a/libstdc++-v3/include/parallel/for_each.h b/libstdc++-v3/include/parallel/for_each.h index b585999f514..e6e573ddbbf 100644 --- a/libstdc++-v3/include/parallel/for_each.h +++ b/libstdc++-v3/include/parallel/for_each.h @@ -42,7 +42,7 @@ namespace __gnu_parallel { - /** @brief Chose the desired algorithm by evaluating @__c __parallelism_tag. + /** @brief Chose the desired algorithm by evaluating @c __parallelism_tag. * @param __begin Begin iterator of input sequence. * @param __end End iterator of input sequence. * @param __user_op A user-specified functor (comparator, predicate, @@ -69,31 +69,21 @@ namespace __gnu_parallel _Parallelism __parallelism_tag) { if (__parallelism_tag == parallel_unbalanced) - return __for_each_template_random_access_ed(__begin, __end, __user_op, - __functionality, __reduction, - __reduction_start, - __output, __bound); + return __for_each_template_random_access_ed + (__begin, __end, __user_op, __functionality, __reduction, + __reduction_start, __output, __bound); else if (__parallelism_tag == parallel_omp_loop) - return __for_each_template_random_access_omp_loop( - __begin, __end, __user_op, - __functionality, - __reduction, - __reduction_start, - __output, __bound); + return __for_each_template_random_access_omp_loop + (__begin, __end, __user_op, __functionality, __reduction, + __reduction_start, __output, __bound); else if (__parallelism_tag == parallel_omp_loop_static) - return __for_each_template_random_access_omp_loop( - __begin, __end, __user_op, - __functionality, - __reduction, - __reduction_start, - __output, __bound); + return __for_each_template_random_access_omp_loop + (__begin, __end, __user_op, __functionality, __reduction, + __reduction_start, __output, __bound); else //e. g. parallel_balanced - return __for_each_template_random_access_workstealing(__begin, __end, - __user_op, - __functionality, - __reduction, - __reduction_start, - __output, __bound); + return __for_each_template_random_access_workstealing + (__begin, __end, __user_op, __functionality, __reduction, + __reduction_start, __output, __bound); } } diff --git a/libstdc++-v3/include/parallel/for_each_selectors.h b/libstdc++-v3/include/parallel/for_each_selectors.h index 092398de0f9..3a37e5ca637 100644 --- a/libstdc++-v3/include/parallel/for_each_selectors.h +++ b/libstdc++-v3/include/parallel/for_each_selectors.h @@ -37,17 +37,15 @@ namespace __gnu_parallel { - /** @brief Generic __selector for embarrassingly parallel functions. */ template<typename _It> - struct __generic_for_each_selector - { - /** @brief _Iterator on last element processed; needed for some - * algorithms (e. g. std::transform()). - */ - _It _M_finish_iterator; - }; - + struct __generic_for_each_selector + { + /** @brief _Iterator on last element processed; needed for some + * algorithms (e. g. std::transform()). + */ + _It _M_finish_iterator; + }; /** @brief std::for_each() selector. */ template<typename _It> @@ -220,21 +218,21 @@ namespace __gnu_parallel }; /** @brief std::inner_product() selector. */ - template<typename _It, typename It2, typename _Tp> + template<typename _It, typename _It2, typename _Tp> struct __inner_product_selector : public __generic_for_each_selector<_It> { /** @brief Begin iterator of first sequence. */ - _It __begin1_iterator; + _It __begin1_iterator; /** @brief Begin iterator of second sequence. */ - It2 begin2_iterator; + _It2 __begin2_iterator; /** @brief Constructor. * @param b1 Begin iterator of first sequence. * @param b2 Begin iterator of second sequence. */ explicit - __inner_product_selector(_It b1, It2 b2) - : __begin1_iterator(b1), begin2_iterator(b2) { } + __inner_product_selector(_It __b1, _It2 __b2) + : __begin1_iterator(__b1), __begin2_iterator(__b2) { } /** @brief Functor execution. * @param __mult Multiplication functor. @@ -246,7 +244,7 @@ namespace __gnu_parallel { typename std::iterator_traits<_It>::difference_type __position = __current - __begin1_iterator; - return __mult(*__current, *(begin2_iterator + __position)); + return __mult(*__current, *(__begin2_iterator + __position)); } }; @@ -268,8 +266,8 @@ namespace __gnu_parallel * __elements. */ template<typename _It> - struct __adjacent_difference_selector : - public __generic_for_each_selector<_It> + struct __adjacent_difference_selector + : public __generic_for_each_selector<_It> { template<typename _Op> bool @@ -277,7 +275,7 @@ namespace __gnu_parallel { typename _It::first_type __go_back_one = __i.first; --__go_back_one; - *__i.__second = __o(*__i.__first, *__go_back_one); + *__i.second = __o(*__i.first, *__go_back_one); return true; } }; @@ -293,14 +291,14 @@ namespace __gnu_parallel * @param __i iterator referencing object. */ template<typename _It> void - operator()(_It __i) { } + operator()(_It) { } }; /** @brief Reduction function doing nothing. */ struct _DummyReduct { bool - operator()(bool /*__x*/, bool /*__y*/) const + operator()(bool, bool) const { return true; } }; @@ -315,12 +313,7 @@ namespace __gnu_parallel _It operator()(_It __x, _It __y) - { - if (__comp(*__x, *__y)) - return __x; - else - return __y; - } + { return (__comp(*__x, *__y)) ? __x : __y; } }; /** @brief Reduction for finding the maximum element, using a comparator. */ @@ -334,12 +327,7 @@ namespace __gnu_parallel _It operator()(_It __x, _It __y) - { - if (__comp(*__x, *__y)) - return __y; - else - return __x; - } + { return (__comp(*__x, *__y)) ? __y : __x; } }; /** @brief General reduction, using a binary operator. */ diff --git a/libstdc++-v3/include/parallel/list_partition.h b/libstdc++-v3/include/parallel/list_partition.h index 9c4f48187f0..1f1bfa22e44 100644 --- a/libstdc++-v3/include/parallel/list_partition.h +++ b/libstdc++-v3/include/parallel/list_partition.h @@ -42,17 +42,17 @@ namespace __gnu_parallel * @param __os_starts Start positions worked on (oversampled). * @param __count_to_two Counts up to 2. * @param __range_length Current length of a chunk. - * @param __make_twice Whether the @__c __os_starts is allowed to be + * @param __make_twice Whether the @c __os_starts is allowed to be * grown or not */ template<typename _IIter> void __shrink_and_double(std::vector<_IIter>& __os_starts, - size_t& __count_to_two, size_t& __range_length, - const bool __make_twice) + size_t& __count_to_two, size_t& __range_length, + const bool __make_twice) { ++__count_to_two; - if (not __make_twice or __count_to_two < 2) + if (!__make_twice || __count_to_two < 2) __shrink(__os_starts, __count_to_two, __range_length); else { @@ -68,7 +68,7 @@ namespace __gnu_parallel template<typename _IIter> void __shrink(std::vector<_IIter>& __os_starts, size_t& __count_to_two, - size_t& __range_length) + size_t& __range_length) { for (typename std::vector<_IIter>::size_type __i = 0; __i <= (__os_starts.size() / 2); ++__i) @@ -83,16 +83,17 @@ namespace __gnu_parallel * @param __begin Begin iterator of input sequence. * @param __end End iterator of input sequence. * @param __starts Start iterators for the resulting parts, dimension - * @__c __num_parts+1. For convenience, @__c __starts @__c [__num_parts] + * @c __num_parts+1. For convenience, @c __starts @c [__num_parts] * contains the end iterator of the sequence. * @param __lengths Length of the resulting parts. * @param __num_parts Number of parts to split the sequence into. * @param __f Functor to be applied to each element by traversing __it * @param __oversampling Oversampling factor. If 0, then the - * partitions will differ in at most @__f$ \sqrt{\mathrm{__end} - - * \mathrm{__begin}} @__f$ __elements. Otherwise, the ratio between the - * longest and the shortest part is bounded by @__f$ - * 1/(\mathrm{__oversampling} \cdot \mathrm{num\_parts}) @__f$. + * partitions will differ in at most + * \sqrt{\mathrm{__end} - \mathrm{__begin}} + * __elements. Otherwise, the ratio between the + * longest and the shortest part is bounded by + * 1/(\mathrm{__oversampling} \cdot \mathrm{num\_parts}) * @return Length of the whole sequence. */ template<typename _IIter, typename _FunctorType> @@ -112,8 +113,8 @@ namespace __gnu_parallel std::vector<_IIter> __os_starts(2 * __oversampling * __num_parts + 1); - __os_starts[0]= __begin; - _IIter __prev = __begin, __it = __begin; + __os_starts[0] = __begin; + _IIter __prev = __begin, __it = __begin; size_t __dist_limit = 0, __dist = 0; size_t __cur = 1, __next = 1; size_t __range_length = 1; diff --git a/libstdc++-v3/include/parallel/losertree.h b/libstdc++-v3/include/parallel/losertree.h index 0da84abe4ab..425cf6d4b6f 100644 --- a/libstdc++-v3/include/parallel/losertree.h +++ b/libstdc++-v3/include/parallel/losertree.h @@ -40,992 +40,1000 @@ namespace __gnu_parallel { - -/** - * @brief Guarded loser/tournament tree. - * - * The smallest element is at the top. - * - * Guarding is done explicitly through one flag _M_sup per element, - * inf is not needed due to a better initialization routine. This - * is a well-performing variant. - * - * @param _Tp the element type - * @param _Compare the comparator to use, defaults to std::less<_Tp> - */ -template<typename _Tp, typename _Compare> -class _LoserTreeBase -{ -protected: - /** @brief Internal representation of a _LoserTree element. */ - struct _Loser - { - /** @brief flag, true iff this is a "maximum" __sentinel. */ - bool _M_sup; - /** @brief __index of the __source __sequence. */ - int _M_source; - /** @brief _M_key of the element in the _LoserTree. */ - _Tp _M_key; - }; - - unsigned int _M_ik, _M_k, _M_offset; - - /** log_2{_M_k} */ - unsigned int _M_log_k; - - /** @brief _LoserTree __elements. */ - _Loser* _M_losers; - - /** @brief _Compare to use. */ - _Compare _M_comp; - /** - * @brief State flag that determines whether the _LoserTree is empty. + * @brief Guarded loser/tournament tree. * - * Only used for building the _LoserTree. - */ - bool _M_first_insert; - -public: - /** - * @brief The constructor. + * The smallest element is at the top. + * + * Guarding is done explicitly through one flag _M_sup per element, + * inf is not needed due to a better initialization routine. This + * is a well-performing variant. * - * @param __k The number of sequences to merge. - * @param __comp The comparator to use. + * @param _Tp the element type + * @param _Compare the comparator to use, defaults to std::less<_Tp> */ - _LoserTreeBase(unsigned int __k, _Compare __comp) - : _M_comp(__comp) - { - _M_ik = __k; - - // Compute log_2{_M_k} for the _Loser Tree - _M_log_k = __rd_log2(_M_ik - 1) + 1; - - // Next greater power of 2. - _M_k = 1 << _M_log_k; - _M_offset = _M_k; - - // Avoid default-constructing _M_losers[]._M_key - _M_losers - = static_cast<_Loser*>(::operator new(2 * _M_k * sizeof(_Loser))); - for (unsigned int __i = _M_ik - 1; __i < _M_k; ++__i) - _M_losers[__i + _M_k]._M_sup = true; + template<typename _Tp, typename _Compare> + class _LoserTreeBase + { + protected: + /** @brief Internal representation of a _LoserTree element. */ + struct _Loser + { + /** @brief flag, true iff this is a "maximum" __sentinel. */ + bool _M_sup; + /** @brief __index of the __source __sequence. */ + int _M_source; + /** @brief _M_key of the element in the _LoserTree. */ + _Tp _M_key; + }; + + unsigned int _M_ik, _M_k, _M_offset; + + /** log_2{_M_k} */ + unsigned int _M_log_k; + + /** @brief _LoserTree __elements. */ + _Loser* _M_losers; + + /** @brief _Compare to use. */ + _Compare _M_comp; + + /** + * @brief State flag that determines whether the _LoserTree is empty. + * + * Only used for building the _LoserTree. + */ + bool _M_first_insert; + + public: + /** + * @brief The constructor. + * + * @param __k The number of sequences to merge. + * @param __comp The comparator to use. + */ + _LoserTreeBase(unsigned int __k, _Compare __comp) + : _M_comp(__comp) + { + _M_ik = __k; - _M_first_insert = true; - } + // Compute log_2{_M_k} for the _Loser Tree + _M_log_k = __rd_log2(_M_ik - 1) + 1; - /** - * @brief The destructor. - */ - ~_LoserTreeBase() - { ::operator delete(_M_losers); } + // Next greater power of 2. + _M_k = 1 << _M_log_k; + _M_offset = _M_k; - /** - * @brief Initializes the sequence "_M_source" with the element "_M_key". - * - * @param _M_key the element to insert - * @param _M_source __index of the __source __sequence - * @param _M_sup flag that determines whether the value to insert is an - * explicit __supremum. - */ - inline void - __insert_start(const _Tp& _M_key, int _M_source, bool _M_sup) - { - unsigned int __pos = _M_k + _M_source; + // Avoid default-constructing _M_losers[]._M_key + _M_losers = static_cast<_Loser*>(::operator new(2 * _M_k + * sizeof(_Loser))); + for (unsigned int __i = _M_ik - 1; __i < _M_k; ++__i) + _M_losers[__i + _M_k]._M_sup = true; - if(_M_first_insert) - { - // Construct all keys, so we can easily deconstruct them. - for (unsigned int __i = 0; __i < (2 * _M_k); ++__i) - new(&(_M_losers[__i]._M_key)) _Tp(_M_key); - _M_first_insert = false; + _M_first_insert = true; } - else - new(&(_M_losers[__pos]._M_key)) _Tp(_M_key); - - _M_losers[__pos]._M_sup = _M_sup; - _M_losers[__pos]._M_source = _M_source; - } - /** - * @return the index of the sequence with the smallest element. - */ - int __get_min_source() - { return _M_losers[0]._M_source; } -}; - -/** - * @brief Stable _LoserTree variant. - * - * Provides the stable implementations of insert_start, __init_winner, - * __init and __delete_min_insert. - * - * Unstable variant is done using partial specialisation below. - */ -template<bool __stable/* default == true */, typename _Tp, typename _Compare> -class _LoserTree : public _LoserTreeBase<_Tp, _Compare> -{ - typedef _LoserTreeBase<_Tp, _Compare> Base; - using Base::_M_k; - using Base::_M_losers; - using Base::_M_first_insert; - -public: - _LoserTree(unsigned int __k, _Compare __comp) - : Base::_LoserTreeBase(__k, __comp) - {} - - unsigned int - __init_winner(unsigned int __root) - { - if (__root >= _M_k) + /** + * @brief The destructor. + */ + ~_LoserTreeBase() + { ::operator delete(_M_losers); } + + /** + * @brief Initializes the sequence "_M_source" with the element "__key". + * + * @param __key the element to insert + * @param __source __index of the __source __sequence + * @param __sup flag that determines whether the value to insert is an + * explicit __supremum. + */ + void + __insert_start(const _Tp& __key, int __source, bool __sup) { - return __root; + unsigned int __pos = _M_k + __source; + + if(_M_first_insert) + { + // Construct all keys, so we can easily deconstruct them. + for (unsigned int __i = 0; __i < (2 * _M_k); ++__i) + new(&(_M_losers[__i]._M_key)) _Tp(__key); + _M_first_insert = false; + } + else + new(&(_M_losers[__pos]._M_key)) _Tp(__key); + + _M_losers[__pos]._M_sup = __sup; + _M_losers[__pos]._M_source = __source; } - else + + /** + * @return the index of the sequence with the smallest element. + */ + int __get_min_source() + { return _M_losers[0]._M_source; } + }; + + /** + * @brief Stable _LoserTree variant. + * + * Provides the stable implementations of insert_start, __init_winner, + * __init and __delete_min_insert. + * + * Unstable variant is done using partial specialisation below. + */ + template<bool __stable/* default == true */, typename _Tp, + typename _Compare> + class _LoserTree + : public _LoserTreeBase<_Tp, _Compare> + { + typedef _LoserTreeBase<_Tp, _Compare> _Base; + using _Base::_M_k; + using _Base::_M_losers; + using _Base::_M_first_insert; + + public: + _LoserTree(unsigned int __k, _Compare __comp) + : _Base::_LoserTreeBase(__k, __comp) + { } + + unsigned int + __init_winner(unsigned int __root) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); - if (_M_losers[__right]._M_sup - || (!_M_losers[__left]._M_sup - && !_M_comp(_M_losers[__right]._M_key, _M_losers[__left]._M_key))) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); + if (_M_losers[__right]._M_sup + || (!_M_losers[__left]._M_sup + && !_M_comp(_M_losers[__right]._M_key, + _M_losers[__left]._M_key))) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - } - - void __init() - { _M_losers[0] = _M_losers[__init_winner(1)]; } - /** - * @brief Delete the smallest element and insert a new element from - * the previously smallest element's sequence. - * - * This implementation is stable. - */ - // Do not pass a const reference since _M_key will be used as local variable. - void __delete_min_insert(_Tp _M_key, bool _M_sup) - { + void __init() + { _M_losers[0] = _M_losers[__init_winner(1)]; } + + /** + * @brief Delete the smallest element and insert a new element from + * the previously smallest element's sequence. + * + * This implementation is stable. + */ + // Do not pass a const reference since __key will be used as + // local variable. + void + __delete_min_insert(_Tp __key, bool __sup) + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted, ties are broken by _M_source. + if ((__sup && (!_M_losers[__pos]._M_sup + || _M_losers[__pos]._M_source < __source)) + || (!__sup && !_M_losers[__pos]._M_sup + && ((_M_comp(_M_losers[__pos]._M_key, __key)) + || (!_M_comp(__key, _M_losers[__pos]._M_key) + && _M_losers[__pos]._M_source < __source)))) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_sup, __sup); + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_key, __key); + } + } + + _M_losers[0]._M_sup = __sup; + _M_losers[0]._M_source = __source; + _M_losers[0]._M_key = __key; + } + }; + + /** + * @brief Unstable _LoserTree variant. + * + * Stability (non-stable here) is selected with partial specialization. + */ + template<typename _Tp, typename _Compare> + class _LoserTree</* __stable == */false, _Tp, _Compare> + : public _LoserTreeBase<_Tp, _Compare> + { + typedef _LoserTreeBase<_Tp, _Compare> _Base; + using _Base::_M_log_k; + using _Base::_M_k; + using _Base::_M_losers; + using _Base::_M_first_insert; + + public: + _LoserTree(unsigned int __k, _Compare __comp) + : _Base::_LoserTreeBase(__k, __comp) + { } + + /** + * Computes the winner of the competition at position "__root". + * + * Called recursively (starting at 0) to build the initial tree. + * + * @param __root __index of the "game" to start. + */ + unsigned int + __init_winner(unsigned int __root) { - // The smaller one gets promoted, ties are broken by _M_source. - if ((_M_sup && (!_M_losers[__pos]._M_sup - || _M_losers[__pos]._M_source < _M_source)) - || (!_M_sup && !_M_losers[__pos]._M_sup - && ((_M_comp(_M_losers[__pos]._M_key, _M_key)) - || (!_M_comp(_M_key, _M_losers[__pos]._M_key) - && _M_losers[__pos]._M_source < _M_source)))) - { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_sup, _M_sup); - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_key, _M_key); - } + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); + if (_M_losers[__right]._M_sup + || (!_M_losers[__left]._M_sup + && !_M_comp(_M_losers[__right]._M_key, + _M_losers[__left]._M_key))) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - _M_losers[0]._M_sup = _M_sup; - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_key = _M_key; - } -}; - -/** - * @brief Unstable _LoserTree variant. - * - * Stability (non-stable here) is selected with partial specialization. - */ -template<typename _Tp, typename _Compare> -class _LoserTree</* __stable == */false, _Tp, _Compare> : - public _LoserTreeBase<_Tp, _Compare> -{ - typedef _LoserTreeBase<_Tp, _Compare> Base; - using Base::_M_log_k; - using Base::_M_k; - using Base::_M_losers; - using Base::_M_first_insert; + void + __init() + { _M_losers[0] = _M_losers[__init_winner(1)]; } + + /** + * Delete the _M_key smallest element and insert the element __key + * instead. + * + * @param __key the _M_key to insert + * @param __sup true iff __key is an explicitly marked supremum + */ + // Do not pass a const reference since __key will be used as local + // variable. + void + __delete_min_insert(_Tp __key, bool __sup) + { +#if _GLIBCXX_ASSERTIONS + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); +#endif -public: - _LoserTree(unsigned int __k, _Compare __comp) - : Base::_LoserTreeBase(__k, __comp) - {} + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted. + if (__sup || (!_M_losers[__pos]._M_sup + && _M_comp(_M_losers[__pos]._M_key, __key))) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_sup, __sup); + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_key, __key); + } + } + + _M_losers[0]._M_sup = __sup; + _M_losers[0]._M_source = __source; + _M_losers[0]._M_key = __key; + } + }; /** - * Computes the winner of the competition at position "__root". - * - * Called recursively (starting at 0) to build the initial tree. - * - * @param __root __index of the "game" to start. + * @brief Base class of _Loser Tree implementation using pointers. */ - unsigned int - __init_winner (unsigned int __root) - { - if (__root >= _M_k) + template<typename _Tp, typename _Compare> + class _LoserTreePointerBase + { + protected: + /** @brief Internal representation of _LoserTree __elements. */ + struct _Loser { - return __root; - } - else + bool _M_sup; + int _M_source; + const _Tp* _M_keyp; + }; + + unsigned int _M_ik, _M_k, _M_offset; + _Loser* _M_losers; + _Compare _M_comp; + + public: + _LoserTreePointerBase(unsigned int __k, + _Compare __comp = std::less<_Tp>()) + : _M_comp(__comp) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); - if (_M_losers[__right]._M_sup - || (!_M_losers[__left]._M_sup - && !_M_comp(_M_losers[__right]._M_key, _M_losers[__left]._M_key))) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + _M_ik = __k; + + // Next greater power of 2. + _M_k = 1 << (__rd_log2(_M_ik - 1) + 1); + _M_offset = _M_k; + _M_losers = new _Loser[_M_k * 2]; + for (unsigned int __i = _M_ik - 1; __i < _M_k; __i++) + _M_losers[__i + _M_k]._M_sup = true; } - } - inline void - __init() - { _M_losers[0] = _M_losers[__init_winner(1)]; } + ~_LoserTreePointerBase() + { ::operator delete[](_M_losers); } - /** - * Delete the _M_key smallest element and insert the element _M_key instead. - * - * @param _M_key the _M_key to insert - * @param _M_sup true iff _M_key is an explicitly marked supremum - */ - // Do not pass a const reference since _M_key will be used as local variable. - inline void - __delete_min_insert(_Tp _M_key, bool _M_sup) - { -#if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); -#endif + int __get_min_source() + { return _M_losers[0]._M_source; } - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) - { - // The smaller one gets promoted. - if (_M_sup || (!_M_losers[__pos]._M_sup - && _M_comp(_M_losers[__pos]._M_key, _M_key))) + void __insert_start(const _Tp& __key, int __source, bool __sup) { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_sup, _M_sup); - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_key, _M_key); + unsigned int __pos = _M_k + __source; + + _M_losers[__pos]._M_sup = __sup; + _M_losers[__pos]._M_source = __source; + _M_losers[__pos]._M_keyp = &__key; } - } + }; - _M_losers[0]._M_sup = _M_sup; - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_key = _M_key; - } -}; + /** + * @brief Stable _LoserTree implementation. + * + * The unstable variant is implemented using partial instantiation below. + */ + template<bool __stable/* default == true */, typename _Tp, typename _Compare> + class _LoserTreePointer + : public _LoserTreePointerBase<_Tp, _Compare> + { + typedef _LoserTreePointerBase<_Tp, _Compare> _Base; + using _Base::_M_k; + using _Base::_M_losers; + public: + _LoserTreePointer(unsigned int __k, _Compare __comp = std::less<_Tp>()) + : _Base::_LoserTreePointerBase(__k, __comp) + { } -/** - * @brief Base class of _Loser Tree implementation using pointers. - */ -template<typename _Tp, typename _Compare> -class _LoserTreePointerBase -{ -protected: - /** @brief Internal representation of _LoserTree __elements. */ - struct _Loser - { - bool _M_sup; - int _M_source; - const _Tp* _M_keyp; - }; - - unsigned int _M_ik, _M_k, _M_offset; - _Loser* _M_losers; - _Compare _M_comp; - -public: - _LoserTreePointerBase(unsigned int __k, _Compare __comp = std::less<_Tp>()) - : _M_comp(__comp) - { - _M_ik = __k; - - // Next greater power of 2. - _M_k = 1 << (__rd_log2(_M_ik - 1) + 1); - _M_offset = _M_k; - _M_losers = new _Loser[_M_k * 2]; - for (unsigned int __i = _M_ik - 1; __i < _M_k; __i++) - _M_losers[__i + _M_k]._M_sup = true; - } - - ~_LoserTreePointerBase() - { ::operator delete[](_M_losers); } - - int __get_min_source() - { return _M_losers[0]._M_source; } - - void __insert_start(const _Tp& _M_key, int _M_source, bool _M_sup) - { - unsigned int __pos = _M_k + _M_source; - - _M_losers[__pos]._M_sup = _M_sup; - _M_losers[__pos]._M_source = _M_source; - _M_losers[__pos]._M_keyp = &_M_key; - } -}; - -/** - * @brief Stable _LoserTree implementation. - * - * The unstable variant is implemented using partial instantiation below. - */ -template<bool __stable/* default == true */, typename _Tp, typename _Compare> -class _LoserTreePointer : public _LoserTreePointerBase<_Tp, _Compare> -{ - typedef _LoserTreePointerBase<_Tp, _Compare> Base; - using Base::_M_k; - using Base::_M_losers; - -public: - _LoserTreePointer(unsigned int __k, _Compare __comp = std::less<_Tp>()) - : Base::_LoserTreePointerBase(__k, __comp) - {} - - unsigned int - __init_winner(unsigned int __root) - { - if (__root >= _M_k) - { - return __root; - } - else + unsigned int + __init_winner(unsigned int __root) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); - if (_M_losers[__right]._M_sup - || (!_M_losers[__left]._M_sup - && !_M_comp(*_M_losers[__right]._M_keyp, - *_M_losers[__left]._M_keyp))) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); + if (_M_losers[__right]._M_sup + || (!_M_losers[__left]._M_sup + && !_M_comp(*_M_losers[__right]._M_keyp, + *_M_losers[__left]._M_keyp))) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - } - void __init() - { _M_losers[0] = _M_losers[__init_winner(1)]; } + void __init() + { _M_losers[0] = _M_losers[__init_winner(1)]; } - void __delete_min_insert(const _Tp& _M_key, bool _M_sup) - { + void __delete_min_insert(const _Tp& __key, bool __sup) + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - const _Tp* _M_keyp = &_M_key; - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) - { - // The smaller one gets promoted, ties are broken by _M_source. - if ((_M_sup && (!_M_losers[__pos]._M_sup || - _M_losers[__pos]._M_source < _M_source)) || - (!_M_sup && !_M_losers[__pos]._M_sup && - ((_M_comp(*_M_losers[__pos]._M_keyp, *_M_keyp)) || - (!_M_comp(*_M_keyp, *_M_losers[__pos]._M_keyp) - && _M_losers[__pos]._M_source < _M_source)))) - { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_sup, _M_sup); - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_keyp, _M_keyp); - } + const _Tp* __keyp = &__key; + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted, ties are broken by __source. + if ((__sup && (!_M_losers[__pos]._M_sup + || _M_losers[__pos]._M_source < __source)) + || (!__sup && !_M_losers[__pos]._M_sup && + ((_M_comp(*_M_losers[__pos]._M_keyp, *__keyp)) + || (!_M_comp(*__keyp, *_M_losers[__pos]._M_keyp) + && _M_losers[__pos]._M_source < __source)))) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_sup, __sup); + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_keyp, __keyp); + } + } + + _M_losers[0]._M_sup = __sup; + _M_losers[0]._M_source = __source; + _M_losers[0]._M_keyp = __keyp; } + }; - _M_losers[0]._M_sup = _M_sup; - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_keyp = _M_keyp; - } -}; - -/** - * @brief Unstable _LoserTree implementation. - * - * The stable variant is above. - */ -template<typename _Tp, typename _Compare> -class _LoserTreePointer</* __stable == */false, _Tp, _Compare> : - public _LoserTreePointerBase<_Tp, _Compare> -{ - typedef _LoserTreePointerBase<_Tp, _Compare> Base; - using Base::_M_k; - using Base::_M_losers; - -public: - _LoserTreePointer(unsigned int __k, _Compare __comp = std::less<_Tp>()) - : Base::_LoserTreePointerBase(__k, __comp) - {} - - unsigned int - __init_winner(unsigned int __root) - { - if (__root >= _M_k) - { - return __root; - } - else + /** + * @brief Unstable _LoserTree implementation. + * + * The stable variant is above. + */ + template<typename _Tp, typename _Compare> + class _LoserTreePointer</* __stable == */false, _Tp, _Compare> + : public _LoserTreePointerBase<_Tp, _Compare> + { + typedef _LoserTreePointerBase<_Tp, _Compare> _Base; + using _Base::_M_k; + using _Base::_M_losers; + + public: + _LoserTreePointer(unsigned int __k, _Compare __comp = std::less<_Tp>()) + : _Base::_LoserTreePointerBase(__k, __comp) + { } + + unsigned int + __init_winner(unsigned int __root) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); - if (_M_losers[__right]._M_sup - || (!_M_losers[__left]._M_sup - && !_M_comp(*_M_losers[__right]._M_keyp, - *_M_losers[__left]._M_keyp))) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); + if (_M_losers[__right]._M_sup + || (!_M_losers[__left]._M_sup + && !_M_comp(*_M_losers[__right]._M_keyp, + *_M_losers[__left]._M_keyp))) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - } - void __init() - { _M_losers[0] = _M_losers[__init_winner(1)]; } + void __init() + { _M_losers[0] = _M_losers[__init_winner(1)]; } - void __delete_min_insert(const _Tp& _M_key, bool _M_sup) - { + void __delete_min_insert(const _Tp& __key, bool __sup) + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - const _Tp* _M_keyp = &_M_key; - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) - { - // The smaller one gets promoted. - if (_M_sup || (!_M_losers[__pos]._M_sup - && _M_comp(*_M_losers[__pos]._M_keyp, *_M_keyp))) - { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_sup, _M_sup); - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_keyp, _M_keyp); - } + const _Tp* __keyp = &__key; + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted. + if (__sup || (!_M_losers[__pos]._M_sup + && _M_comp(*_M_losers[__pos]._M_keyp, *__keyp))) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_sup, __sup); + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_keyp, __keyp); + } + } + + _M_losers[0]._M_sup = __sup; + _M_losers[0]._M_source = __source; + _M_losers[0]._M_keyp = __keyp; } + }; - _M_losers[0]._M_sup = _M_sup; - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_keyp = _M_keyp; - } -}; - -/** @brief Base class for unguarded _LoserTree implementation. - * - * The whole element is copied into the tree structure. - * - * No guarding is done, therefore not a single input sequence must - * run empty. Unused __sequence heads are marked with a sentinel which - * is > all elements that are to be merged. - * - * This is a very fast variant. - */ -template<typename _Tp, typename _Compare> -class _LoserTreeUnguardedBase -{ -protected: - struct _Loser - { - int _M_source; - _Tp _M_key; - }; - - unsigned int _M_ik, _M_k, _M_offset; - _Loser* _M_losers; - _Compare _M_comp; - -public: - inline - _LoserTreeUnguardedBase(unsigned int __k, const _Tp _sentinel, - _Compare __comp = std::less<_Tp>()) - : _M_comp(__comp) - { - _M_ik = __k; - - // Next greater power of 2. - _M_k = 1 << (__rd_log2(_M_ik - 1) + 1); - _M_offset = _M_k; - // Avoid default-constructing _M_losers[]._M_key - _M_losers - = static_cast<_Loser*>(::operator new(2 * _M_k * sizeof(_Loser))); - - for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i) + /** @brief Base class for unguarded _LoserTree implementation. + * + * The whole element is copied into the tree structure. + * + * No guarding is done, therefore not a single input sequence must + * run empty. Unused __sequence heads are marked with a sentinel which + * is > all elements that are to be merged. + * + * This is a very fast variant. + */ + template<typename _Tp, typename _Compare> + class _LoserTreeUnguardedBase + { + protected: + struct _Loser + { + int _M_source; + _Tp _M_key; + }; + + unsigned int _M_ik, _M_k, _M_offset; + _Loser* _M_losers; + _Compare _M_comp; + + public: + _LoserTreeUnguardedBase(unsigned int __k, const _Tp __sentinel, + _Compare __comp = std::less<_Tp>()) + : _M_comp(__comp) { - _M_losers[__i]._M_key = _sentinel; - _M_losers[__i]._M_source = -1; + _M_ik = __k; + + // Next greater power of 2. + _M_k = 1 << (__rd_log2(_M_ik - 1) + 1); + _M_offset = _M_k; + // Avoid default-constructing _M_losers[]._M_key + _M_losers = static_cast<_Loser*>(::operator new(2 * _M_k + * sizeof(_Loser))); + + for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i) + { + _M_losers[__i]._M_key = __sentinel; + _M_losers[__i]._M_source = -1; + } } - } - inline ~_LoserTreeUnguardedBase() - { ::operator delete(_M_losers); } + ~_LoserTreeUnguardedBase() + { ::operator delete(_M_losers); } - inline int - __get_min_source() - { + int + __get_min_source() + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - return _M_losers[0]._M_source; - } - - inline void - __insert_start(const _Tp& _M_key, int _M_source, bool) - { - unsigned int __pos = _M_k + _M_source; - - new(&(_M_losers[__pos]._M_key)) _Tp(_M_key); - _M_losers[__pos]._M_source = _M_source; - } -}; - -/** - * @brief Stable implementation of unguarded _LoserTree. - * - * Unstable variant is selected below with partial specialization. - */ -template<bool __stable/* default == true */, typename _Tp, typename _Compare> -class _LoserTreeUnguarded : public _LoserTreeUnguardedBase<_Tp, _Compare> -{ - typedef _LoserTreeUnguardedBase<_Tp, _Compare> Base; - using Base::_M_k; - using Base::_M_losers; - -public: - _LoserTreeUnguarded(unsigned int __k, const _Tp _sentinel, - _Compare __comp = std::less<_Tp>()) - : Base::_LoserTreeUnguardedBase(__k, _sentinel, __comp) - {} - - unsigned int - __init_winner(unsigned int __root) - { - if (__root >= _M_k) + return _M_losers[0]._M_source; + } + + void + __insert_start(const _Tp& __key, int __source, bool) { - return __root; + unsigned int __pos = _M_k + __source; + + new(&(_M_losers[__pos]._M_key)) _Tp(__key); + _M_losers[__pos]._M_source = __source; } - else + }; + + /** + * @brief Stable implementation of unguarded _LoserTree. + * + * Unstable variant is selected below with partial specialization. + */ + template<bool __stable/* default == true */, typename _Tp, typename _Compare> + class _LoserTreeUnguarded + : public _LoserTreeUnguardedBase<_Tp, _Compare> + { + typedef _LoserTreeUnguardedBase<_Tp, _Compare> _Base; + using _Base::_M_k; + using _Base::_M_losers; + + public: + _LoserTreeUnguarded(unsigned int __k, const _Tp __sentinel, + _Compare __comp = std::less<_Tp>()) + : _Base::_LoserTreeUnguardedBase(__k, __sentinel, __comp) + { } + + unsigned int + __init_winner(unsigned int __root) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); - if (!_M_comp(_M_losers[__right]._M_key, _M_losers[__left]._M_key)) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); + if (!_M_comp(_M_losers[__right]._M_key, + _M_losers[__left]._M_key)) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - } - inline void - __init() - { - _M_losers[0] = _M_losers[__init_winner(1)]; + void + __init() + { + _M_losers[0] = _M_losers[__init_winner(1)]; #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top at the beginning (0 sequences!) - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top at the beginning + // (0 sequences!) + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - } + } - // Do not pass a const reference since _M_key will be used as local variable. - inline void - __delete_min_insert(_Tp _M_key, bool) - { + // Do not pass a const reference since __key will be used as + // local variable. + void + __delete_min_insert(_Tp __key, bool) + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) - { - // The smaller one gets promoted, ties are broken by _M_source. - if (_M_comp(_M_losers[__pos]._M_key, _M_key) - || (!_M_comp(_M_key, _M_losers[__pos]._M_key) - && _M_losers[__pos]._M_source < _M_source)) - { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_key, _M_key); - } + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted, ties are broken by _M_source. + if (_M_comp(_M_losers[__pos]._M_key, __key) + || (!_M_comp(__key, _M_losers[__pos]._M_key) + && _M_losers[__pos]._M_source < __source)) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_key, __key); + } + } + + _M_losers[0]._M_source = __source; + _M_losers[0]._M_key = __key; } + }; - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_key = _M_key; - } -}; - -/** - * @brief Non-Stable implementation of unguarded _LoserTree. - * - * Stable implementation is above. - */ -template<typename _Tp, typename _Compare> -class _LoserTreeUnguarded</* __stable == */false, _Tp, _Compare> : - public _LoserTreeUnguardedBase<_Tp, _Compare> -{ - typedef _LoserTreeUnguardedBase<_Tp, _Compare> Base; - using Base::_M_k; - using Base::_M_losers; - -public: - _LoserTreeUnguarded(unsigned int __k, const _Tp _sentinel, - _Compare __comp = std::less<_Tp>()) - : Base::_LoserTreeUnguardedBase(__k, _sentinel, __comp) - {} - - unsigned int - __init_winner (unsigned int __root) - { - if (__root >= _M_k) - { - return __root; - } - else + /** + * @brief Non-Stable implementation of unguarded _LoserTree. + * + * Stable implementation is above. + */ + template<typename _Tp, typename _Compare> + class _LoserTreeUnguarded</* __stable == */false, _Tp, _Compare> + : public _LoserTreeUnguardedBase<_Tp, _Compare> + { + typedef _LoserTreeUnguardedBase<_Tp, _Compare> _Base; + using _Base::_M_k; + using _Base::_M_losers; + + public: + _LoserTreeUnguarded(unsigned int __k, const _Tp __sentinel, + _Compare __comp = std::less<_Tp>()) + : _Base::_LoserTreeUnguardedBase(__k, __sentinel, __comp) + { } + + unsigned int + __init_winner(unsigned int __root) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); #if _GLIBCXX_ASSERTIONS - // If __left one is sentinel then __right one must be, too. - if (_M_losers[__left]._M_source == -1) - _GLIBCXX_PARALLEL_ASSERT(_M_losers[__right]._M_source == -1); + // If __left one is sentinel then __right one must be, too. + if (_M_losers[__left]._M_source == -1) + _GLIBCXX_PARALLEL_ASSERT(_M_losers[__right]._M_source == -1); #endif - if (!_M_comp(_M_losers[__right]._M_key, _M_losers[__left]._M_key)) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + if (!_M_comp(_M_losers[__right]._M_key, + _M_losers[__left]._M_key)) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - } - inline void - __init() - { - _M_losers[0] = _M_losers[__init_winner(1)]; + void + __init() + { + _M_losers[0] = _M_losers[__init_winner(1)]; #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top at the beginning (0 sequences!) - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top at the beginning + // (0 sequences!) + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - } + } - // Do not pass a const reference since _M_key will be used as local variable. - inline void - __delete_min_insert(_Tp _M_key, bool) - { + // Do not pass a const reference since __key will be used as + // local variable. + void + __delete_min_insert(_Tp __key, bool) + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) - { - // The smaller one gets promoted. - if (_M_comp(_M_losers[__pos]._M_key, _M_key)) - { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_key, _M_key); - } + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted. + if (_M_comp(_M_losers[__pos]._M_key, __key)) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_key, __key); + } + } + + _M_losers[0]._M_source = __source; + _M_losers[0]._M_key = __key; } + }; + + /** @brief Unguarded loser tree, keeping only pointers to the + * elements in the tree structure. + * + * No guarding is done, therefore not a single input sequence must + * run empty. This is a very fast variant. + */ + template<typename _Tp, typename _Compare> + class _LoserTreePointerUnguardedBase + { + protected: + struct _Loser + { + int _M_source; + const _Tp* _M_keyp; + }; - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_key = _M_key; - } -}; + unsigned int _M_ik, _M_k, _M_offset; + _Loser* _M_losers; + _Compare _M_comp; -/** @brief Unguarded loser tree, keeping only pointers to the -* elements in the tree structure. -* -* No guarding is done, therefore not a single input sequence must -* run empty. This is a very fast variant. -*/ -template<typename _Tp, typename _Compare> -class LoserTreePointerUnguardedBase -{ -protected: - struct _Loser - { - int _M_source; - const _Tp* _M_keyp; - }; - - unsigned int _M_ik, _M_k, _M_offset; - _Loser* _M_losers; - _Compare _M_comp; - -public: - - inline - LoserTreePointerUnguardedBase(unsigned int __k, const _Tp& _sentinel, - _Compare __comp = std::less<_Tp>()) - : _M_comp(__comp) - { - _M_ik = __k; - - // Next greater power of 2. - _M_k = 1 << (__rd_log2(_M_ik - 1) + 1); - _M_offset = _M_k; - // Avoid default-constructing _M_losers[]._M_key - _M_losers = new _Loser[2 * _M_k]; - - for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i) + public: + + _LoserTreePointerUnguardedBase(unsigned int __k, const _Tp& __sentinel, + _Compare __comp = std::less<_Tp>()) + : _M_comp(__comp) { - _M_losers[__i]._M_keyp = &_sentinel; - _M_losers[__i]._M_source = -1; + _M_ik = __k; + + // Next greater power of 2. + _M_k = 1 << (__rd_log2(_M_ik - 1) + 1); + _M_offset = _M_k; + // Avoid default-constructing _M_losers[]._M_key + _M_losers = new _Loser[2 * _M_k]; + + for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i) + { + _M_losers[__i]._M_keyp = &__sentinel; + _M_losers[__i]._M_source = -1; + } } - } - inline ~LoserTreePointerUnguardedBase() - { delete[] _M_losers; } + ~_LoserTreePointerUnguardedBase() + { delete[] _M_losers; } - inline int - __get_min_source() - { + int + __get_min_source() + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - return _M_losers[0]._M_source; - } - - inline void - __insert_start(const _Tp& _M_key, int _M_source, bool) - { - unsigned int __pos = _M_k + _M_source; - - _M_losers[__pos]._M_keyp = &_M_key; - _M_losers[__pos]._M_source = _M_source; - } -}; - -/** - * @brief Stable unguarded _LoserTree variant storing pointers. - * - * Unstable variant is implemented below using partial specialization. - */ -template<bool __stable/* default == true */, typename _Tp, typename _Compare> -class _LoserTreePointerUnguarded : - public LoserTreePointerUnguardedBase<_Tp, _Compare> -{ - typedef LoserTreePointerUnguardedBase<_Tp, _Compare> Base; - using Base::_M_k; - using Base::_M_losers; - -public: - _LoserTreePointerUnguarded(unsigned int __k, const _Tp& _sentinel, - _Compare __comp = std::less<_Tp>()) - : Base::LoserTreePointerUnguardedBase(__k, _sentinel, __comp) - {} - - unsigned int - __init_winner(unsigned int __root) - { - if (__root >= _M_k) + return _M_losers[0]._M_source; + } + + void + __insert_start(const _Tp& __key, int __source, bool) { - return __root; + unsigned int __pos = _M_k + __source; + + _M_losers[__pos]._M_keyp = &__key; + _M_losers[__pos]._M_source = __source; } - else + }; + + /** + * @brief Stable unguarded _LoserTree variant storing pointers. + * + * Unstable variant is implemented below using partial specialization. + */ + template<bool __stable/* default == true */, typename _Tp, typename _Compare> + class _LoserTreePointerUnguarded + : public _LoserTreePointerUnguardedBase<_Tp, _Compare> + { + typedef _LoserTreePointerUnguardedBase<_Tp, _Compare> _Base; + using _Base::_M_k; + using _Base::_M_losers; + + public: + _LoserTreePointerUnguarded(unsigned int __k, const _Tp& __sentinel, + _Compare __comp = std::less<_Tp>()) + : _Base::_LoserTreePointerUnguardedBase(__k, __sentinel, __comp) + { } + + unsigned int + __init_winner(unsigned int __root) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); - if (!_M_comp(*_M_losers[__right]._M_keyp, *_M_losers[__left]._M_keyp)) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); + if (!_M_comp(*_M_losers[__right]._M_keyp, + *_M_losers[__left]._M_keyp)) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - } - inline void - __init() - { - _M_losers[0] = _M_losers[__init_winner(1)]; + void + __init() + { + _M_losers[0] = _M_losers[__init_winner(1)]; #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top at the beginning (0 sequences!) - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top at the beginning + // (0 sequences!) + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - } + } - inline void - __delete_min_insert(const _Tp& _M_key, bool _M_sup) - { + void + __delete_min_insert(const _Tp& __key, bool __sup) + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - const _Tp* _M_keyp = &_M_key; - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) - { - // The smaller one gets promoted, ties are broken by _M_source. - if (_M_comp(*_M_losers[__pos]._M_keyp, *_M_keyp) - || (!_M_comp(*_M_keyp, *_M_losers[__pos]._M_keyp) - && _M_losers[__pos]._M_source < _M_source)) - { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_keyp, _M_keyp); - } + const _Tp* __keyp = &__key; + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted, ties are broken by _M_source. + if (_M_comp(*_M_losers[__pos]._M_keyp, *__keyp) + || (!_M_comp(*__keyp, *_M_losers[__pos]._M_keyp) + && _M_losers[__pos]._M_source < __source)) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_keyp, __keyp); + } + } + + _M_losers[0]._M_source = __source; + _M_losers[0]._M_keyp = __keyp; } + }; - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_keyp = _M_keyp; - } -}; - -/** - * @brief Unstable unguarded _LoserTree variant storing pointers. - * - * Stable variant is above. - */ -template<typename _Tp, typename _Compare> -class _LoserTreePointerUnguarded</* __stable == */false, _Tp, _Compare> : - public LoserTreePointerUnguardedBase<_Tp, _Compare> -{ - typedef LoserTreePointerUnguardedBase<_Tp, _Compare> Base; - using Base::_M_k; - using Base::_M_losers; - -public: - _LoserTreePointerUnguarded(unsigned int __k, const _Tp& _sentinel, - _Compare __comp = std::less<_Tp>()) - : Base::LoserTreePointerUnguardedBase(__k, _sentinel, __comp) - {} - - unsigned int - __init_winner(unsigned int __root) - { - if (__root >= _M_k) - { - return __root; - } - else + /** + * @brief Unstable unguarded _LoserTree variant storing pointers. + * + * Stable variant is above. + */ + template<typename _Tp, typename _Compare> + class _LoserTreePointerUnguarded</* __stable == */false, _Tp, _Compare> + : public _LoserTreePointerUnguardedBase<_Tp, _Compare> + { + typedef _LoserTreePointerUnguardedBase<_Tp, _Compare> _Base; + using _Base::_M_k; + using _Base::_M_losers; + + public: + _LoserTreePointerUnguarded(unsigned int __k, const _Tp& __sentinel, + _Compare __comp = std::less<_Tp>()) + : _Base::_LoserTreePointerUnguardedBase(__k, __sentinel, __comp) + { } + + unsigned int + __init_winner(unsigned int __root) { - unsigned int __left = __init_winner (2 * __root); - unsigned int __right = __init_winner (2 * __root + 1); + if (__root >= _M_k) + return __root; + else + { + unsigned int __left = __init_winner(2 * __root); + unsigned int __right = __init_winner(2 * __root + 1); #if _GLIBCXX_ASSERTIONS - // If __left one is sentinel then __right one must be, too. - if (_M_losers[__left]._M_source == -1) - _GLIBCXX_PARALLEL_ASSERT(_M_losers[__right]._M_source == -1); + // If __left one is sentinel then __right one must be, too. + if (_M_losers[__left]._M_source == -1) + _GLIBCXX_PARALLEL_ASSERT(_M_losers[__right]._M_source == -1); #endif - if (!_M_comp(*_M_losers[__right]._M_keyp, *_M_losers[__left]._M_keyp)) - { - // Left one is less or equal. - _M_losers[__root] = _M_losers[__right]; - return __left; - } - else - { - // Right one is less. - _M_losers[__root] = _M_losers[__left]; - return __right; - } + if (!_M_comp(*_M_losers[__right]._M_keyp, + *_M_losers[__left]._M_keyp)) + { + // Left one is less or equal. + _M_losers[__root] = _M_losers[__right]; + return __left; + } + else + { + // Right one is less. + _M_losers[__root] = _M_losers[__left]; + return __right; + } + } } - } - inline void - __init() - { - _M_losers[0] = _M_losers[__init_winner(1)]; + void + __init() + { + _M_losers[0] = _M_losers[__init_winner(1)]; #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top at the beginning (0 sequences!) - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top at the beginning + // (0 sequences!) + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - } + } - inline void - __delete_min_insert(const _Tp& _M_key, bool _M_sup) - { + void + __delete_min_insert(const _Tp& __key, bool __sup) + { #if _GLIBCXX_ASSERTIONS - // no dummy sequence can ever be at the top! - _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); + // no dummy sequence can ever be at the top! + _GLIBCXX_PARALLEL_ASSERT(_M_losers[0]._M_source != -1); #endif - const _Tp* _M_keyp = &_M_key; - int _M_source = _M_losers[0]._M_source; - for (unsigned int __pos = (_M_k + _M_source) / 2; __pos > 0; __pos /= 2) - { - // The smaller one gets promoted. - if (_M_comp(*(_M_losers[__pos]._M_keyp), *_M_keyp)) - { - // The other one is smaller. - std::swap(_M_losers[__pos]._M_source, _M_source); - std::swap(_M_losers[__pos]._M_keyp, _M_keyp); - } + const _Tp* __keyp = &__key; + int __source = _M_losers[0]._M_source; + for (unsigned int __pos = (_M_k + __source) / 2; __pos > 0; + __pos /= 2) + { + // The smaller one gets promoted. + if (_M_comp(*(_M_losers[__pos]._M_keyp), *__keyp)) + { + // The other one is smaller. + std::swap(_M_losers[__pos]._M_source, __source); + std::swap(_M_losers[__pos]._M_keyp, __keyp); + } + } + + _M_losers[0]._M_source = __source; + _M_losers[0]._M_keyp = __keyp; } - - _M_losers[0]._M_source = _M_source; - _M_losers[0]._M_keyp = _M_keyp; - } -}; - + }; } // namespace __gnu_parallel #endif /* _GLIBCXX_PARALLEL_LOSERTREE_H */ diff --git a/libstdc++-v3/include/parallel/merge.h b/libstdc++-v3/include/parallel/merge.h index c323c629893..a19e996a055 100644 --- a/libstdc++-v3/include/parallel/merge.h +++ b/libstdc++-v3/include/parallel/merge.h @@ -37,11 +37,11 @@ namespace __gnu_parallel { - /** @brief Merge routine being able to merge only the @__c __max_length + /** @brief Merge routine being able to merge only the @c __max_length * smallest elements. * - * The @__c __begin iterators are advanced accordingly, they might not - * reach @__c __end, in contrast to the usual variant. + * The @c __begin iterators are advanced accordingly, they might not + * reach @c __end, in contrast to the usual variant. * @param __begin1 Begin iterator of first sequence. * @param __end1 End iterator of first sequence. * @param __begin2 Begin iterator of second sequence. @@ -54,11 +54,10 @@ namespace __gnu_parallel typename _OutputIterator, typename _DifferenceTp, typename _Compare> _OutputIterator - __merge_advance_usual(_RAIter1& __begin1, - _RAIter1 __end1, - _RAIter2& __begin2, - _RAIter2 __end2, _OutputIterator __target, - _DifferenceTp __max_length, _Compare __comp) + __merge_advance_usual(_RAIter1& __begin1, _RAIter1 __end1, + _RAIter2& __begin2, _RAIter2 __end2, + _OutputIterator __target, + _DifferenceTp __max_length, _Compare __comp) { typedef _DifferenceTp _DifferenceType; while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0) @@ -84,11 +83,11 @@ namespace __gnu_parallel return __target; } - /** @brief Merge routine being able to merge only the @__c __max_length + /** @brief Merge routine being able to merge only the @c __max_length * smallest elements. * - * The @__c __begin iterators are advanced accordingly, they might not - * reach @__c __end, in contrast to the usual variant. + * The @c __begin iterators are advanced accordingly, they might not + * reach @c __end, in contrast to the usual variant. * Specially designed code should allow the compiler to generate * conditional moves instead of branches. * @param __begin1 Begin iterator of first sequence. @@ -103,12 +102,10 @@ namespace __gnu_parallel typename _OutputIterator, typename _DifferenceTp, typename _Compare> _OutputIterator - __merge_advance_movc(_RAIter1& __begin1, - _RAIter1 __end1, - _RAIter2& __begin2, - _RAIter2 __end2, - _OutputIterator __target, - _DifferenceTp __max_length, _Compare __comp) + __merge_advance_movc(_RAIter1& __begin1, _RAIter1 __end1, + _RAIter2& __begin2, _RAIter2 __end2, + _OutputIterator __target, + _DifferenceTp __max_length, _Compare __comp) { typedef _DifferenceTp _DifferenceType; typedef typename std::iterator_traits<_RAIter1>::value_type @@ -153,11 +150,11 @@ namespace __gnu_parallel return __target; } - /** @brief Merge routine being able to merge only the @__c __max_length + /** @brief Merge routine being able to merge only the @c __max_length * smallest elements. * - * The @__c __begin iterators are advanced accordingly, they might not - * reach @__c __end, in contrast to the usual variant. + * The @c __begin iterators are advanced accordingly, they might not + * reach @c __end, in contrast to the usual variant. * Static switch on whether to use the conditional-move variant. * @param __begin1 Begin iterator of first sequence. * @param __end1 End iterator of first sequence. @@ -172,14 +169,14 @@ namespace __gnu_parallel typename _Compare> inline _OutputIterator __merge_advance(_RAIter1& __begin1, _RAIter1 __end1, - _RAIter2& __begin2, _RAIter2 __end2, - _OutputIterator __target, _DifferenceTp __max_length, - _Compare __comp) + _RAIter2& __begin2, _RAIter2 __end2, + _OutputIterator __target, _DifferenceTp __max_length, + _Compare __comp) { _GLIBCXX_CALL(__max_length) - return __merge_advance_movc(__begin1, __end1, __begin2, __end2, __target, - __max_length, __comp); + return __merge_advance_movc(__begin1, __end1, __begin2, __end2, + __target, __max_length, __comp); } /** @brief Merge routine fallback to sequential in case the @@ -195,23 +192,21 @@ namespace __gnu_parallel template<typename _RAIter1, typename _RAIter2, typename _RAIter3, typename _Compare> inline _RAIter3 - __parallel_merge_advance(_RAIter1& __begin1, - _RAIter1 __end1, - _RAIter2& __begin2, - // different iterators, parallel implementation - // not available - _RAIter2 __end2, - _RAIter3 __target, typename - std::iterator_traits<_RAIter1>:: - difference_type __max_length, _Compare __comp) + __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1, + _RAIter2& __begin2, + // different iterators, parallel implementation + // not available + _RAIter2 __end2, _RAIter3 __target, typename + std::iterator_traits<_RAIter1>:: + difference_type __max_length, _Compare __comp) { return __merge_advance(__begin1, __end1, __begin2, __end2, __target, - __max_length, __comp); } + __max_length, __comp); } - /** @brief Parallel merge routine being able to merge only the @__c + /** @brief Parallel merge routine being able to merge only the @c * __max_length smallest elements. * - * The @__c __begin iterators are advanced accordingly, they might not - * reach @__c __end, in contrast to the usual variant. + * The @c __begin iterators are advanced accordingly, they might not + * reach @c __end, in contrast to the usual variant. * The functionality is projected onto parallel_multiway_merge. * @param __begin1 Begin iterator of first sequence. * @param __end1 End iterator of first sequence. @@ -225,13 +220,11 @@ namespace __gnu_parallel template<typename _RAIter1, typename _RAIter3, typename _Compare> inline _RAIter3 - __parallel_merge_advance(_RAIter1& __begin1, - _RAIter1 __end1, - _RAIter1& __begin2, - _RAIter1 __end2, - _RAIter3 __target, typename - std::iterator_traits<_RAIter1>:: - difference_type __max_length, _Compare __comp) + __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1, + _RAIter1& __begin2, _RAIter1 __end2, + _RAIter3 __target, typename + std::iterator_traits<_RAIter1>:: + difference_type __max_length, _Compare __comp) { typedef typename std::iterator_traits<_RAIter1>::value_type _ValueType; @@ -242,17 +235,14 @@ namespace __gnu_parallel typedef typename std::pair<_RAIter1, _RAIter1> _IteratorPair; - _IteratorPair - seqs[2] = { std::make_pair(__begin1, __end1), - std::make_pair(__begin2, __end2) }; - _RAIter3 - __target_end = parallel_multiway_merge - < /* __stable = */ true, /* __sentinels = */ false>( - seqs, seqs + 2, __target, - multiway_merge_exact_splitting - < /* __stable = */ true, _IteratorPair*, - _Compare, _DifferenceType1>, - __max_length, __comp, omp_get_max_threads()); + _IteratorPair __seqs[2] = { std::make_pair(__begin1, __end1), + std::make_pair(__begin2, __end2) }; + _RAIter3 __target_end = parallel_multiway_merge + < /* __stable = */ true, /* __sentinels = */ false> + (__seqs, __seqs + 2, __target, multiway_merge_exact_splitting + < /* __stable = */ true, _IteratorPair*, + _Compare, _DifferenceType1>, __max_length, __comp, + omp_get_max_threads()); return __target_end; } diff --git a/libstdc++-v3/include/parallel/multiseq_selection.h b/libstdc++-v3/include/parallel/multiseq_selection.h index fdce872c5a1..e434eee624c 100644 --- a/libstdc++-v3/include/parallel/multiseq_selection.h +++ b/libstdc++-v3/include/parallel/multiseq_selection.h @@ -53,8 +53,8 @@ namespace __gnu_parallel /** @brief Compare __a pair of types lexicographically, ascending. */ template<typename _T1, typename _T2, typename _Compare> class _Lexicographic - : public std::binary_function< - std::pair<_T1, _T2>, std::pair<_T1, _T2>, bool> + : public std::binary_function<std::pair<_T1, _T2>, + std::pair<_T1, _T2>, bool> { private: _Compare& _M_comp; @@ -142,19 +142,19 @@ namespace __gnu_parallel // Number of sequences, number of elements in total (possibly // including padding). - _DifferenceType __m = std::distance(__begin_seqs, __end_seqs), __N = 0, + _DifferenceType __m = std::distance(__begin_seqs, __end_seqs), __nn = 0, __nmax, __n, __r; for (int __i = 0; __i < __m; __i++) { - __N += std::distance(__begin_seqs[__i].first, + __nn += std::distance(__begin_seqs[__i].first, __begin_seqs[__i].second); _GLIBCXX_PARALLEL_ASSERT( std::distance(__begin_seqs[__i].first, __begin_seqs[__i].second) > 0); } - if (__rank == __N) + if (__rank == __nn) { for (int __i = 0; __i < __m; __i++) __begin_offsets[__i] = __begin_seqs[__i].second; // Very end. @@ -163,9 +163,9 @@ namespace __gnu_parallel } _GLIBCXX_PARALLEL_ASSERT(__m != 0); - _GLIBCXX_PARALLEL_ASSERT(__N != 0); + _GLIBCXX_PARALLEL_ASSERT(__nn != 0); _GLIBCXX_PARALLEL_ASSERT(__rank >= 0); - _GLIBCXX_PARALLEL_ASSERT(__rank < __N); + _GLIBCXX_PARALLEL_ASSERT(__rank < __nn); _DifferenceType* __ns = new _DifferenceType[__m]; _DifferenceType* __a = new _DifferenceType[__m]; @@ -187,9 +187,6 @@ namespace __gnu_parallel // equality iff __nmax = 2^__k - 1. __l = (1ULL << __r) - 1; - // From now on, including padding. - __N = __l * __m; - for (int __i = 0; __i < __m; __i++) { __a[__i] = 0; @@ -215,7 +212,7 @@ namespace __gnu_parallel __sample.push_back( std::make_pair(__S(__i)[0] /*__dummy element*/, __i)); - _DifferenceType __localrank = __rank * __m / __N ; + _DifferenceType __localrank = __rank / __l; int __j; for (__j = 0; @@ -265,15 +262,11 @@ namespace __gnu_parallel __b[__i] -= __n + 1; } - _DifferenceType __leftsize = 0, __total = 0; + _DifferenceType __leftsize = 0; for (int __i = 0; __i < __m; __i++) - { __leftsize += __a[__i] / (__n + 1); - __total += __l / (__n + 1); - } - - _DifferenceType __skew = static_cast<_DifferenceType> - (static_cast<uint64_t>(__total) * __rank / __N - __leftsize); + + _DifferenceType __skew = __rank / (__n + 1) - __leftsize; if (__skew > 0) { @@ -408,14 +401,14 @@ namespace __gnu_parallel // Number of sequences, number of elements in total (possibly // including padding). _DifferenceType __m = std::distance(__begin_seqs, __end_seqs); - _DifferenceType __N = 0; + _DifferenceType __nn = 0; _DifferenceType __nmax, __n, __r; for (int __i = 0; __i < __m; __i++) - __N += std::distance(__begin_seqs[__i].first, - __begin_seqs[__i].second); + __nn += std::distance(__begin_seqs[__i].first, + __begin_seqs[__i].second); - if (__m == 0 || __N == 0 || __rank < 0 || __rank >= __N) + if (__m == 0 || __nn == 0 || __rank < 0 || __rank >= __nn) { // result undefined if there is no data or __rank is outside bounds throw std::exception(); @@ -440,10 +433,7 @@ namespace __gnu_parallel // Pad all lists to this length, at least as long as any ns[__i], // equality iff __nmax = 2^__k - 1 - __l = pow2(__r) - 1; - - // From now on, including padding. - __N = __l * __m; + __l = __round_up_to_pow2(__r) - 1; for (int __i = 0; __i < __m; ++__i) { @@ -472,7 +462,7 @@ namespace __gnu_parallel __sample.push_back( std::make_pair(__S(__i)[0] /*__dummy element*/, __i)); - _DifferenceType __localrank = __rank * __m / __N ; + _DifferenceType __localrank = __rank / __l; int __j; for (__j = 0; @@ -513,15 +503,11 @@ namespace __gnu_parallel __b[__i] -= __n + 1; } - _DifferenceType __leftsize = 0, __total = 0; + _DifferenceType __leftsize = 0; for (int __i = 0; __i < __m; ++__i) - { __leftsize += __a[__i] / (__n + 1); - __total += __l / (__n + 1); - } - _DifferenceType __skew = ((unsigned long long)__total * __rank / __N - - __leftsize); + _DifferenceType __skew = __rank / (__n + 1) - __leftsize; if (__skew > 0) { diff --git a/libstdc++-v3/include/parallel/multiway_merge.h b/libstdc++-v3/include/parallel/multiway_merge.h index 310a07a766c..cdf21540d12 100644 --- a/libstdc++-v3/include/parallel/multiway_merge.h +++ b/libstdc++-v3/include/parallel/multiway_merge.h @@ -54,2113 +54,1998 @@ namespace __gnu_parallel { + /** @brief _Iterator wrapper supporting an implicit supremum at the end + * of the sequence, dominating all comparisons. + * + * The implicit supremum comes with a performance cost. + * + * Deriving from _RAIter is not possible since + * _RAIter need not be a class. + */ + template<typename _RAIter, typename _Compare> + class _GuardedIterator + { + private: + /** @brief Current iterator __position. */ + _RAIter _M_current; + + /** @brief End iterator of the sequence. */ + _RAIter _M_end; + + /** @brief _Compare. */ + _Compare& __comp; + + public: + /** @brief Constructor. Sets iterator to beginning of sequence. + * @param __begin Begin iterator of sequence. + * @param __end End iterator of sequence. + * @param __comp Comparator provided for associated overloaded + * compare operators. */ + _GuardedIterator(_RAIter __begin, _RAIter __end, _Compare& __comp) + : _M_current(__begin), _M_end(__end), __comp(__comp) + { } + + /** @brief Pre-increment operator. + * @return This. */ + _GuardedIterator<_RAIter, _Compare>& + operator++() + { + ++_M_current; + return *this; + } -// 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 - * of the sequence, dominating all comparisons. - * - * The implicit supremum comes with a performance cost. - * - * Deriving from _RAIter is not possible since - * _RAIter need not be a class. - */ -template<typename _RAIter, typename _Compare> - class _GuardedIterator - { - private: - /** @brief Current iterator __position. */ - _RAIter _M_current; - - /** @brief End iterator of the sequence. */ - _RAIter _M_end; - - /** @brief _Compare. */ - _Compare& __comp; - - public: - /** @brief Constructor. Sets iterator to beginning of sequence. - * @param __begin Begin iterator of sequence. - * @param _M_end End iterator of sequence. - * @param __comp Comparator provided for associated overloaded - * compare operators. */ - _GuardedIterator(_RAIter __begin, - _RAIter _M_end, _Compare& __comp) - : _M_current(__begin), _M_end(_M_end), __comp(__comp) - { } - - /** @brief Pre-increment operator. - * @return This. */ - _GuardedIterator<_RAIter, _Compare>& - operator++() + /** @brief Dereference operator. + * @return Referenced element. */ + typename std::iterator_traits<_RAIter>::value_type& + operator*() + { return *_M_current; } + + /** @brief Convert to wrapped iterator. + * @return Wrapped iterator. */ + operator _RAIter() + { 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 + 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. */ + friend 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 { - ++_M_current; - return *this; - } + private: + /** @brief Current iterator __position. */ + _RAIter _M_current; + /** @brief _Compare. */ + mutable _Compare& __comp; + + public: + /** @brief Constructor. Sets iterator to beginning of sequence. + * @param __begin Begin iterator of sequence. + * @param __end Unused, only for compatibility. + * @param __comp Unused, only for compatibility. */ + _UnguardedIterator(_RAIter __begin, + _RAIter /* __end */, _Compare& __comp) + : _M_current(__begin), __comp(__comp) + { } + + /** @brief Pre-increment operator. + * @return This. */ + _UnguardedIterator<_RAIter, _Compare>& + operator++() + { + ++_M_current; + return *this; + } - /** @brief Dereference operator. - * @return Referenced element. */ - typename std::iterator_traits<_RAIter>::value_type& - operator*() - { return *_M_current; } - - /** @brief Convert to wrapped iterator. - * @return Wrapped iterator. */ - operator _RAIter() - { return _M_current; } - - friend bool - operator< <_RAIter, _Compare>( - _GuardedIterator<_RAIter, _Compare>& __bi1, - _GuardedIterator<_RAIter, _Compare>& __bi2); - - friend bool - operator<= <_RAIter, _Compare>( - _GuardedIterator<_RAIter, _Compare>& __bi1, - _GuardedIterator<_RAIter, _Compare>& __bi2); - }; - -/** @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> - class _UnguardedIterator - { - private: - /** @brief Current iterator __position. */ - _RAIter _M_current; - /** @brief _Compare. */ - mutable _Compare& __comp; - - public: - /** @brief Constructor. Sets iterator to beginning of sequence. - * @param __begin Begin iterator of sequence. - * @param _M_end Unused, only for compatibility. - * @param __comp Unused, only for compatibility. */ - _UnguardedIterator(_RAIter __begin, - _RAIter _M_end, _Compare& __comp) - : _M_current(__begin), __comp(__comp) - { } - - /** @brief Pre-increment operator. - * @return This. */ - _UnguardedIterator<_RAIter, _Compare>& - operator++() + /** @brief Dereference operator. + * @return Referenced element. */ + typename std::iterator_traits<_RAIter>::value_type& + operator*() + { return *_M_current; } + + /** @brief Convert to wrapped iterator. + * @return Wrapped iterator. */ + operator _RAIter() + { 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 + 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. */ + friend bool + operator<=(_UnguardedIterator<_RAIter, _Compare>& __bi1, + _UnguardedIterator<_RAIter, _Compare>& __bi2) + { + // Normal compare. + return !(__bi1.__comp)(*__bi2, *__bi1); + } + }; + + /** @brief Highly efficient 3-way merging procedure. + * + * Merging is done with the algorithm implementation described by Peter + * Sanders. Basically, the idea is to minimize the number of necessary + * comparison after merging an element. The implementation trick + * that makes this fast is that the order of the sequences is stored + * in the instruction pointer (translated into labels in C++). + * + * This works well for merging up to 4 sequences. + * + * Note that making the merging stable does <em>not</em> come at a + * performance hit. + * + * Whether the merging is done guarded or unguarded is selected by the + * used iterator class. + * + * @param __seqs_begin Begin iterator of iterator pair input sequence. + * @param __seqs_end End iterator of iterator pair input sequence. + * @param __target Begin iterator of output sequence. + * @param __comp Comparator. + * @param __length Maximum length to merge, less equal than the + * total number of elements available. + * + * @return End iterator of output sequence. + */ + template<template<typename RAI, typename C> class iterator, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + _RAIter3 + multiway_merge_3_variant(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _DifferenceTp __length, _Compare __comp) { - ++_M_current; - return *this; - } + _GLIBCXX_CALL(__length); - /** @brief Dereference operator. - * @return Referenced element. */ - typename std::iterator_traits<_RAIter>::value_type& - operator*() - { return *_M_current; } - - /** @brief Convert to wrapped iterator. - * @return Wrapped iterator. */ - operator _RAIter() - { return _M_current; } - - friend bool - operator< <_RAIter, _Compare>( - _UnguardedIterator<_RAIter, _Compare>& __bi1, - _UnguardedIterator<_RAIter, _Compare>& __bi2); - - friend bool - operator<= <_RAIter, _Compare>( - _UnguardedIterator<_RAIter, _Compare>& __bi1, - _UnguardedIterator<_RAIter, _Compare>& __bi2); - }; - -/** @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. - * - * Merging is done with the algorithm implementation described by Peter - * Sanders. Basically, the idea is to minimize the number of necessary - * comparison after merging an element. The implementation trick - * that makes this fast is that the order of the sequences is stored - * in the instruction pointer (translated into labels in C++). - * - * This works well for merging up to 4 sequences. - * - * Note that making the merging stable does <em>not</em> come at a - * performance hit. - * - * Whether the merging is done guarded or unguarded is selected by the - * used iterator class. - * - * @param __seqs_begin Begin iterator of iterator pair input sequence. - * @param __seqs_end End iterator of iterator pair input sequence. - * @param __target Begin iterator of output sequence. - * @param __comp Comparator. - * @param __length Maximum length to merge, less equal than the - * total number of elements available. - * - * @return End iterator of output sequence. - */ -template<template<typename RAI, typename C> class iterator, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> - _RAIter3 - multiway_merge_3_variant( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _DifferenceTp __length, _Compare __comp) - { - _GLIBCXX_CALL(__length); - - typedef _DifferenceTp _DifferenceType; - - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; - - if (__length == 0) - return __target; + typedef _DifferenceTp _DifferenceType; + + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; + + if (__length == 0) + return __target; #if _GLIBCXX_ASSERTIONS - _DifferenceTp orig_length = __length; + _DifferenceTp __orig_length = __length; #endif - iterator<_RAIter1, _Compare> - __seq0(__seqs_begin[0].first, __seqs_begin[0].second, __comp), - __seq1(__seqs_begin[1].first, __seqs_begin[1].second, __comp), - __seq2(__seqs_begin[2].first, __seqs_begin[2].second, __comp); + iterator<_RAIter1, _Compare> + __seq0(__seqs_begin[0].first, __seqs_begin[0].second, __comp), + __seq1(__seqs_begin[1].first, __seqs_begin[1].second, __comp), + __seq2(__seqs_begin[2].first, __seqs_begin[2].second, __comp); - if (__seq0 <= __seq1) - { - if (__seq1 <= __seq2) - goto __s012; - else - if (__seq2 < __seq0) - goto __s201; + if (__seq0 <= __seq1) + { + if (__seq1 <= __seq2) + goto __s012; else - goto __s021; - } - else - { - if (__seq1 <= __seq2) - { - if (__seq0 <= __seq2) - goto __s102; + if (__seq2 < __seq0) + goto __s201; else - goto __s120; - } - else - goto __s210; - } -#define _GLIBCXX_PARALLEL_MERGE_3_CASE(__a,__b,__c,c0,c1) \ - __s ## __a ## __b ## __c : \ - *__target = *__seq ## __a; \ - ++__target; \ - --__length; \ - ++__seq ## __a; \ - if (__length == 0) goto finish; \ - if (__seq ## __a c0 __seq ## __b) goto __s ## __a ## __b ## __c; \ - if (__seq ## __a c1 __seq ## __c) goto __s ## __b ## __a ## __c; \ - goto __s ## __b ## __c ## __a; - - _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 1, 2, <=, <=); - _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 2, 0, <=, < ); - _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 0, 1, < , < ); - _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 0, 2, < , <=); - _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 2, 1, <=, <=); - _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 1, 0, < , < ); + goto __s021; + } + else + { + if (__seq1 <= __seq2) + { + if (__seq0 <= __seq2) + goto __s102; + else + goto __s120; + } + else + goto __s210; + } +#define _GLIBCXX_PARALLEL_MERGE_3_CASE(__a, __b, __c, __c0, __c1) \ + __s ## __a ## __b ## __c : \ + *__target = *__seq ## __a; \ + ++__target; \ + --__length; \ + ++__seq ## __a; \ + if (__length == 0) goto __finish; \ + if (__seq ## __a __c0 __seq ## __b) goto __s ## __a ## __b ## __c; \ + if (__seq ## __a __c1 __seq ## __c) goto __s ## __b ## __a ## __c; \ + goto __s ## __b ## __c ## __a; + + _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 1, 2, <=, <=); + _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 2, 0, <=, < ); + _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 0, 1, < , < ); + _GLIBCXX_PARALLEL_MERGE_3_CASE(1, 0, 2, < , <=); + _GLIBCXX_PARALLEL_MERGE_3_CASE(0, 2, 1, <=, <=); + _GLIBCXX_PARALLEL_MERGE_3_CASE(2, 1, 0, < , < ); #undef _GLIBCXX_PARALLEL_MERGE_3_CASE - finish: - ; + __finish: + ; #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT( - ((_RAIter1)__seq0 - __seqs_begin[0].first) + - ((_RAIter1)__seq1 - __seqs_begin[1].first) + - ((_RAIter1)__seq2 - __seqs_begin[2].first) - == orig_length); + _GLIBCXX_PARALLEL_ASSERT( + ((_RAIter1)__seq0 - __seqs_begin[0].first) + + ((_RAIter1)__seq1 - __seqs_begin[1].first) + + ((_RAIter1)__seq2 - __seqs_begin[2].first) + == __orig_length); #endif - __seqs_begin[0].first = __seq0; - __seqs_begin[1].first = __seq1; - __seqs_begin[2].first = __seq2; - - return __target; - } - -/** - * @brief Highly efficient 4-way merging procedure. - * - * Merging is done with the algorithm implementation described by Peter - * Sanders. Basically, the idea is to minimize the number of necessary - * comparison after merging an element. The implementation trick - * that makes this fast is that the order of the sequences is stored - * in the instruction pointer (translated into goto labels in C++). - * - * This works well for merging up to 4 sequences. - * - * Note that making the merging stable does <em>not</em> come at a - * performance hit. - * - * Whether the merging is done guarded or unguarded is selected by the - * used iterator class. - * - * @param __seqs_begin Begin iterator of iterator pair input sequence. - * @param __seqs_end End iterator of iterator pair input sequence. - * @param __target Begin iterator of output sequence. - * @param __comp Comparator. - * @param __length Maximum length to merge, less equal than the - * total number of elements available. - * - * @return End iterator of output sequence. - */ -template<template<typename RAI, typename C> class iterator, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> - _RAIter3 - multiway_merge_4_variant(_RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _DifferenceTp __length, _Compare __comp) - { - _GLIBCXX_CALL(__length); - typedef _DifferenceTp _DifferenceType; - - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; - - iterator<_RAIter1, _Compare> - __seq0(__seqs_begin[0].first, __seqs_begin[0].second, __comp), - __seq1(__seqs_begin[1].first, __seqs_begin[1].second, __comp), - __seq2(__seqs_begin[2].first, __seqs_begin[2].second, __comp), - __seq3(__seqs_begin[3].first, __seqs_begin[3].second, __comp); - -#define _GLIBCXX_PARALLEL_DECISION(__a,__b,__c,d) { \ - if (__seq ## d < __seq ## __a) goto __s ## d ## __a ## __b ## __c; \ - if (__seq ## d < __seq ## __b) goto __s ## __a ## d ## __b ## __c; \ - if (__seq ## d < __seq ## __c) goto __s ## __a ## __b ## d ## __c; \ - goto __s ## __a ## __b ## __c ## d; } - - if (__seq0 <= __seq1) - { - if (__seq1 <= __seq2) - _GLIBCXX_PARALLEL_DECISION(0,1,2,3) - else - if (__seq2 < __seq0) - _GLIBCXX_PARALLEL_DECISION(2,0,1,3) - else - _GLIBCXX_PARALLEL_DECISION(0,2,1,3) - } - else - { - if (__seq1 <= __seq2) - { - if (__seq0 <= __seq2) - _GLIBCXX_PARALLEL_DECISION(1,0,2,3) - else - _GLIBCXX_PARALLEL_DECISION(1,2,0,3) - } - else - _GLIBCXX_PARALLEL_DECISION(2,1,0,3) - } + __seqs_begin[0].first = __seq0; + __seqs_begin[1].first = __seq1; + __seqs_begin[2].first = __seq2; -#define _GLIBCXX_PARALLEL_MERGE_4_CASE(__a,__b,__c,d,c0,c1,c2) \ - __s ## __a ## __b ## __c ## d: \ - if (__length == 0) goto finish; \ - *__target = *__seq ## __a; \ - ++__target; \ - --__length; \ - ++__seq ## __a; \ - if (__seq ## __a c0 __seq ## __b) goto __s ## __a ## __b ## __c ## d; \ - if (__seq ## __a c1 __seq ## __c) goto __s ## __b ## __a ## __c ## d; \ - if (__seq ## __a c2 __seq ## d) goto __s ## __b ## __c ## __a ## d; \ - goto __s ## __b ## __c ## d ## __a; - - _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 2, 3, <=, <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 3, 2, <=, <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 1, 3, <=, <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 3, 1, <=, <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 1, 2, <=, <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 2, 1, <=, <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 2, 3, < , <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 3, 2, < , <=, <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 0, 3, <=, < , <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 3, 0, <=, <=, < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 0, 2, <=, < , <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 2, 0, <=, <=, < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 1, 3, < , < , <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 3, 1, < , <=, < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 0, 3, < , < , <=); - _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 3, 0, < , <=, < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 0, 1, <=, < , < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 1, 0, <=, < , < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 1, 2, < , < , < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 2, 1, < , < , < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 0, 2, < , < , < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 2, 0, < , < , < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 0, 1, < , < , < ); - _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 1, 0, < , < , < ); + return __target; + } + + /** + * @brief Highly efficient 4-way merging procedure. + * + * Merging is done with the algorithm implementation described by Peter + * Sanders. Basically, the idea is to minimize the number of necessary + * comparison after merging an element. The implementation trick + * that makes this fast is that the order of the sequences is stored + * in the instruction pointer (translated into goto labels in C++). + * + * This works well for merging up to 4 sequences. + * + * Note that making the merging stable does <em>not</em> come at a + * performance hit. + * + * Whether the merging is done guarded or unguarded is selected by the + * used iterator class. + * + * @param __seqs_begin Begin iterator of iterator pair input sequence. + * @param __seqs_end End iterator of iterator pair input sequence. + * @param __target Begin iterator of output sequence. + * @param __comp Comparator. + * @param __length Maximum length to merge, less equal than the + * total number of elements available. + * + * @return End iterator of output sequence. + */ + template<template<typename RAI, typename C> class iterator, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + _RAIter3 + multiway_merge_4_variant(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _DifferenceTp __length, _Compare __comp) + { + _GLIBCXX_CALL(__length); + typedef _DifferenceTp _DifferenceType; + + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; + + iterator<_RAIter1, _Compare> + __seq0(__seqs_begin[0].first, __seqs_begin[0].second, __comp), + __seq1(__seqs_begin[1].first, __seqs_begin[1].second, __comp), + __seq2(__seqs_begin[2].first, __seqs_begin[2].second, __comp), + __seq3(__seqs_begin[3].first, __seqs_begin[3].second, __comp); + +#define _GLIBCXX_PARALLEL_DECISION(__a, __b, __c, __d) { \ + if (__seq ## __d < __seq ## __a) \ + goto __s ## __d ## __a ## __b ## __c; \ + if (__seq ## __d < __seq ## __b) \ + goto __s ## __a ## __d ## __b ## __c; \ + if (__seq ## __d < __seq ## __c) \ + goto __s ## __a ## __b ## __d ## __c; \ + goto __s ## __a ## __b ## __c ## __d; } + + if (__seq0 <= __seq1) + { + if (__seq1 <= __seq2) + _GLIBCXX_PARALLEL_DECISION(0,1,2,3) + else + if (__seq2 < __seq0) + _GLIBCXX_PARALLEL_DECISION(2,0,1,3) + else + _GLIBCXX_PARALLEL_DECISION(0,2,1,3) + } + else + { + if (__seq1 <= __seq2) + { + if (__seq0 <= __seq2) + _GLIBCXX_PARALLEL_DECISION(1,0,2,3) + else + _GLIBCXX_PARALLEL_DECISION(1,2,0,3) + } + else + _GLIBCXX_PARALLEL_DECISION(2,1,0,3) + } + +#define _GLIBCXX_PARALLEL_MERGE_4_CASE(__a, __b, __c, __d, \ + __c0, __c1, __c2) \ + __s ## __a ## __b ## __c ## __d: \ + if (__length == 0) goto __finish; \ + *__target = *__seq ## __a; \ + ++__target; \ + --__length; \ + ++__seq ## __a; \ + if (__seq ## __a __c0 __seq ## __b) \ + goto __s ## __a ## __b ## __c ## __d; \ + if (__seq ## __a __c1 __seq ## __c) \ + goto __s ## __b ## __a ## __c ## __d; \ + if (__seq ## __a __c2 __seq ## __d) \ + goto __s ## __b ## __c ## __a ## __d; \ + goto __s ## __b ## __c ## __d ## __a; + + _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 2, 3, <=, <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 1, 3, 2, <=, <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 1, 3, <=, <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 2, 3, 1, <=, <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 1, 2, <=, <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(0, 3, 2, 1, <=, <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 2, 3, < , <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 0, 3, 2, < , <=, <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 0, 3, <=, < , <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 2, 3, 0, <=, <=, < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 0, 2, <=, < , <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(1, 3, 2, 0, <=, <=, < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 1, 3, < , < , <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 0, 3, 1, < , <=, < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 0, 3, < , < , <=); + _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 1, 3, 0, < , <=, < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 0, 1, <=, < , < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(2, 3, 1, 0, <=, < , < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 1, 2, < , < , < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 0, 2, 1, < , < , < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 0, 2, < , < , < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 1, 2, 0, < , < , < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 0, 1, < , < , < ); + _GLIBCXX_PARALLEL_MERGE_4_CASE(3, 2, 1, 0, < , < , < ); #undef _GLIBCXX_PARALLEL_MERGE_4_CASE #undef _GLIBCXX_PARALLEL_DECISION - finish: - ; - - __seqs_begin[0].first = __seq0; - __seqs_begin[1].first = __seq1; - __seqs_begin[2].first = __seq2; - __seqs_begin[3].first = __seq3; - - return __target; - } - -/** @brief Multi-way merging procedure for a high branching factor, - * guarded case. - * - * This merging variant uses a LoserTree class as selected by <tt>LT</tt>. - * - * Stability is selected through the used LoserTree class <tt>LT</tt>. - * - * At least one non-empty sequence is required. - * - * @param __seqs_begin Begin iterator of iterator pair input sequence. - * @param __seqs_end End iterator of iterator pair input sequence. - * @param __target Begin iterator of output sequence. - * @param __comp Comparator. - * @param __length Maximum length to merge, less equal than the - * total number of elements available. - * - * @return End iterator of output sequence. - */ -template<typename LT, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> - _RAIter3 - multiway_merge_loser_tree(_RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _DifferenceTp __length, _Compare __comp) - { - _GLIBCXX_CALL(__length) + __finish: + ; - typedef _DifferenceTp _DifferenceType; - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; + __seqs_begin[0].first = __seq0; + __seqs_begin[1].first = __seq1; + __seqs_begin[2].first = __seq2; + __seqs_begin[3].first = __seq3; - int __k = static_cast<int>(__seqs_end - __seqs_begin); + return __target; + } - LT __lt(__k, __comp); + /** @brief Multi-way merging procedure for a high branching factor, + * guarded case. + * + * This merging variant uses a LoserTree class as selected by <tt>_LT</tt>. + * + * Stability is selected through the used LoserTree class <tt>_LT</tt>. + * + * At least one non-empty sequence is required. + * + * @param __seqs_begin Begin iterator of iterator pair input sequence. + * @param __seqs_end End iterator of iterator pair input sequence. + * @param __target Begin iterator of output sequence. + * @param __comp Comparator. + * @param __length Maximum length to merge, less equal than the + * total number of elements available. + * + * @return End iterator of output sequence. + */ + template<typename _LT, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + _RAIter3 + multiway_merge_loser_tree(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _DifferenceTp __length, _Compare __comp) + { + _GLIBCXX_CALL(__length) - // Default value for potentially non-default-constructible types. - _ValueType* __arbitrary_element = NULL; + typedef _DifferenceTp _DifferenceType; + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; - for (int __t = 0; __t < __k; ++__t) - { - if(__arbitrary_element == NULL - && _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__t]) > 0) - __arbitrary_element = &(*__seqs_begin[__t].first); - } + int __k = static_cast<int>(__seqs_end - __seqs_begin); - for (int __t = 0; __t < __k; ++__t) - { - if (__seqs_begin[__t].first == __seqs_begin[__t].second) - __lt.__insert_start(*__arbitrary_element, __t, true); - else - __lt.__insert_start(*__seqs_begin[__t].first, __t, false); - } + _LT __lt(__k, __comp); - __lt.__init(); + // Default value for potentially non-default-constructible types. + _ValueType* __arbitrary_element = NULL; - int __source; + for (int __t = 0; __t < __k; ++__t) + { + if(__arbitrary_element == NULL + && _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__t]) > 0) + __arbitrary_element = &(*__seqs_begin[__t].first); + } - for (_DifferenceType __i = 0; __i < __length; ++__i) - { - //take out - __source = __lt.__get_min_source(); + for (int __t = 0; __t < __k; ++__t) + { + if (__seqs_begin[__t].first == __seqs_begin[__t].second) + __lt.__insert_start(*__arbitrary_element, __t, true); + else + __lt.__insert_start(*__seqs_begin[__t].first, __t, false); + } - *(__target++) = *(__seqs_begin[__source].first++); + __lt.__init(); - // Feed. - if (__seqs_begin[__source].first == __seqs_begin[__source].second) - __lt.__delete_min_insert(*__arbitrary_element, true); - else - // Replace from same __source. - __lt.__delete_min_insert(*__seqs_begin[__source].first, false); - } + int __source; - return __target; - } - -/** @brief Multi-way merging procedure for a high branching factor, - * unguarded case. - * - * Merging is done using the LoserTree class <tt>LT</tt>. - * - * Stability is selected by the used LoserTrees. - * - * @pre No input will run out of elements during the merge. - * - * @param __seqs_begin Begin iterator of iterator pair input sequence. - * @param __seqs_end End iterator of iterator pair input sequence. - * @param __target Begin iterator of output sequence. - * @param __comp Comparator. - * @param __length Maximum length to merge, less equal than the - * total number of elements available. - * - * @return End iterator of output sequence. - */ -template<typename LT, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, typename _Compare> - _RAIter3 - multiway_merge_loser_tree_unguarded( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - const typename std::iterator_traits<typename std::iterator_traits< - _RAIterIterator>::value_type::first_type>::value_type& - __sentinel, - _DifferenceTp __length, - _Compare __comp) - { - _GLIBCXX_CALL(__length) - typedef _DifferenceTp _DifferenceType; + for (_DifferenceType __i = 0; __i < __length; ++__i) + { + //take out + __source = __lt.__get_min_source(); - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; + *(__target++) = *(__seqs_begin[__source].first++); - int __k = __seqs_end - __seqs_begin; + // Feed. + if (__seqs_begin[__source].first == __seqs_begin[__source].second) + __lt.__delete_min_insert(*__arbitrary_element, true); + else + // Replace from same __source. + __lt.__delete_min_insert(*__seqs_begin[__source].first, false); + } - LT __lt(__k, __sentinel, __comp); + return __target; + } - for (int __t = 0; __t < __k; ++__t) - { -#if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(__seqs_begin[__t].first - != __seqs_begin[__t].second); -#endif - __lt.__insert_start(*__seqs_begin[__t].first, __t, false); - } + /** @brief Multi-way merging procedure for a high branching factor, + * unguarded case. + * + * Merging is done using the LoserTree class <tt>_LT</tt>. + * + * Stability is selected by the used LoserTrees. + * + * @pre No input will run out of elements during the merge. + * + * @param __seqs_begin Begin iterator of iterator pair input sequence. + * @param __seqs_end End iterator of iterator pair input sequence. + * @param __target Begin iterator of output sequence. + * @param __comp Comparator. + * @param __length Maximum length to merge, less equal than the + * total number of elements available. + * + * @return End iterator of output sequence. + */ + template<typename _LT, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, typename _Compare> + _RAIter3 + multiway_merge_loser_tree_unguarded(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + const typename std::iterator_traits<typename std::iterator_traits< + _RAIterIterator>::value_type::first_type>::value_type& + __sentinel, + _DifferenceTp __length, + _Compare __comp) + { + _GLIBCXX_CALL(__length) + typedef _DifferenceTp _DifferenceType; - __lt.__init(); + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; + + int __k = __seqs_end - __seqs_begin; - int __source; + _LT __lt(__k, __sentinel, __comp); + for (int __t = 0; __t < __k; ++__t) + { #if _GLIBCXX_ASSERTIONS - _DifferenceType __i = 0; + _GLIBCXX_PARALLEL_ASSERT(__seqs_begin[__t].first + != __seqs_begin[__t].second); #endif + __lt.__insert_start(*__seqs_begin[__t].first, __t, false); + } - _RAIter3 __target_end = __target + __length; - while (__target < __target_end) - { - // Take out. - __source = __lt.__get_min_source(); + __lt.__init(); + + int __source; #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(0 <= __source && __source < __k); - _GLIBCXX_PARALLEL_ASSERT(__i == 0 - || !__comp(*(__seqs_begin[__source].first), *(__target - 1))); + _DifferenceType __i = 0; #endif - // Feed. - *(__target++) = *(__seqs_begin[__source].first++); + _RAIter3 __target_end = __target + __length; + while (__target < __target_end) + { + // Take out. + __source = __lt.__get_min_source(); #if _GLIBCXX_ASSERTIONS - ++__i; + _GLIBCXX_PARALLEL_ASSERT(0 <= __source && __source < __k); + _GLIBCXX_PARALLEL_ASSERT(__i == 0 + || !__comp(*(__seqs_begin[__source].first), *(__target - 1))); #endif - // Replace from same __source. - __lt.__delete_min_insert(*__seqs_begin[__source].first, false); - } - return __target; - } - - -/** @brief Multi-way merging procedure for a high branching factor, - * requiring sentinels to exist. - * - * @param __stable The value must the same as for the used LoserTrees. - * @param UnguardedLoserTree _Loser Tree variant to use for the unguarded - * merging. - * @param GuardedLoserTree _Loser Tree variant to use for the guarded - * merging. - * - * @param __seqs_begin Begin iterator of iterator pair input sequence. - * @param __seqs_end End iterator of iterator pair input sequence. - * @param __target Begin iterator of output sequence. - * @param __comp Comparator. - * @param __length Maximum length to merge, less equal than the - * total number of elements available. - * - * @return End iterator of output sequence. - */ -template< - typename UnguardedLoserTree, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> - _RAIter3 - multiway_merge_loser_tree_sentinel( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - const typename std::iterator_traits<typename std::iterator_traits< - _RAIterIterator>::value_type::first_type>::value_type& - __sentinel, - _DifferenceTp __length, - _Compare __comp) - { - _GLIBCXX_CALL(__length) - - typedef _DifferenceTp _DifferenceType; - typedef std::iterator_traits<_RAIterIterator> _TraitsType; - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; - - _RAIter3 __target_end; - - for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) - // Move the sequence ends to the sentinel. This has the - // effect that the sentinel appears to be within the sequence. Then, - // we can use the unguarded variant if we merge out as many - // non-sentinel elements as we have. - ++((*__s).second); - - __target_end = multiway_merge_loser_tree_unguarded - <UnguardedLoserTree> - (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); + // Feed. + *(__target++) = *(__seqs_begin[__source].first++); #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(__target_end == __target + __length); - _GLIBCXX_PARALLEL_ASSERT(__is_sorted(__target, __target_end, __comp)); + ++__i; #endif + // Replace from same __source. + __lt.__delete_min_insert(*__seqs_begin[__source].first, false); + } - // Restore the sequence ends so the sentinels are not contained in the - // sequence any more (see comment in loop above). - for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) - --((*__s).second); - - return __target_end; - } - -/** - * @brief Traits for determining whether the loser tree should - * use pointers or copies. - * - * The field "_M_use_pointer" is used to determine whether to use pointers in - * the loser trees or whether to copy the values into the loser tree. - * - * The default behavior is to use pointers if the data type is 4 times as - * big as the pointer to it. - * - * Specialize for your data type to customize the behavior. - * - * Example: - * - * template<> - * struct _LoserTreeTraits<int> - * { static const bool _M_use_pointer = false; }; - * - * template<> - * struct _LoserTreeTraits<heavyweight_type> - * { static const bool _M_use_pointer = true; }; - * - * @param _Tp type to give the loser tree traits for. - */ -template <typename _Tp> -struct _LoserTreeTraits -{ - /** - * @brief True iff to use pointers instead of values in loser trees. + return __target; + } + + + /** @brief Multi-way merging procedure for a high branching factor, + * requiring sentinels to exist. * - * The default behavior is to use pointers if the data type is four - * times as big as the pointer to it. + * @param __stable The value must the same as for the used LoserTrees. + * @param UnguardedLoserTree _Loser Tree variant to use for the unguarded + * merging. + * @param GuardedLoserTree _Loser Tree variant to use for the guarded + * merging. + * + * @param __seqs_begin Begin iterator of iterator pair input sequence. + * @param __seqs_end End iterator of iterator pair input sequence. + * @param __target Begin iterator of output sequence. + * @param __comp Comparator. + * @param __length Maximum length to merge, less equal than the + * total number of elements available. + * + * @return End iterator of output sequence. */ - static const bool _M_use_pointer = (sizeof(_Tp) > 4 * sizeof(_Tp*)); -}; - -/** - * @brief Switch for 3-way merging with __sentinels turned off. - * - * Note that 3-way merging is always stable! - */ -template< - bool __sentinels /*default == false*/, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> -struct __multiway_merge_3_variant_sentinel_switch -{ - _RAIter3 operator()( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _DifferenceTp __length, _Compare __comp) - { - return multiway_merge_3_variant<_GuardedIterator>( - __seqs_begin, __seqs_end, __target, __length, __comp); - } -}; - -/** - * @brief Switch for 3-way merging with __sentinels turned on. - * - * Note that 3-way merging is always stable! - */ -template< - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> -struct __multiway_merge_3_variant_sentinel_switch - <true, _RAIterIterator, _RAIter3, - _DifferenceTp, _Compare> -{ - _RAIter3 operator()( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _DifferenceTp __length, _Compare __comp) - { - return multiway_merge_3_variant<_UnguardedIterator>( - __seqs_begin, __seqs_end, __target, __length, __comp); - } -}; - -/** - * @brief Switch for 4-way merging with __sentinels turned off. - * - * Note that 4-way merging is always stable! - */ -template< - bool __sentinels /*default == false*/, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> -struct __multiway_merge_4_variant_sentinel_switch -{ - _RAIter3 operator()( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _DifferenceTp __length, _Compare __comp) - { - return multiway_merge_4_variant<_GuardedIterator>( - __seqs_begin, __seqs_end, __target, __length, __comp); - } -}; - -/** - * @brief Switch for 4-way merging with __sentinels turned on. - * - * Note that 4-way merging is always stable! - */ -template< - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> -struct __multiway_merge_4_variant_sentinel_switch - <true, _RAIterIterator, _RAIter3, - _DifferenceTp, _Compare> -{ - _RAIter3 operator()( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _DifferenceTp __length, _Compare __comp) - { - return multiway_merge_4_variant<_UnguardedIterator>( - __seqs_begin, __seqs_end, __target, __length, __comp); - } -}; - -/** - * @brief Switch for k-way merging with __sentinels turned on. - */ -template< - bool __sentinels, - bool __stable, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> -struct __multiway_merge_k_variant_sentinel_switch -{ - _RAIter3 operator()( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, + template<typename UnguardedLoserTree, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + _RAIter3 + multiway_merge_loser_tree_sentinel(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, const typename std::iterator_traits<typename std::iterator_traits< - _RAIterIterator>::value_type::first_type>::value_type& - __sentinel, - _DifferenceTp __length, _Compare __comp) - { - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; - - return multiway_merge_loser_tree_sentinel< - typename __gnu_cxx::__conditional_type< - _LoserTreeTraits<_ValueType>::_M_use_pointer - , _LoserTreePointerUnguarded<__stable, _ValueType, _Compare> - , _LoserTreeUnguarded<__stable, _ValueType, _Compare> - >::__type>( - __seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); - } -}; - -/** - * @brief Switch for k-way merging with __sentinels turned off. - */ -template< - bool __stable, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> -struct __multiway_merge_k_variant_sentinel_switch - <false, __stable, _RAIterIterator, _RAIter3, - _DifferenceTp, _Compare> -{ - _RAIter3 operator()( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - const typename std::iterator_traits<typename std::iterator_traits< - _RAIterIterator>::value_type::first_type>::value_type& - __sentinel, - _DifferenceTp __length, _Compare __comp) - { - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; - - return multiway_merge_loser_tree< - typename __gnu_cxx::__conditional_type< - _LoserTreeTraits<_ValueType>::_M_use_pointer - , _LoserTreePointer<__stable, _ValueType, _Compare> - , _LoserTree<__stable, _ValueType, _Compare> - >::__type >(__seqs_begin, __seqs_end, __target, __length, __comp); - } -}; - -/** @brief Sequential multi-way merging switch. - * - * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor and - * runtime settings. - * @param __seqs_begin Begin iterator of iterator pair input sequence. - * @param __seqs_end End iterator of iterator pair input sequence. - * @param __target Begin iterator of output sequence. - * @param __comp Comparator. - * @param __length Maximum length to merge, possibly larger than the - * number of elements available. - * @param __stable Stable merging incurs a performance penalty. - * @param __sentinel The sequences have __a __sentinel element. - * @return End iterator of output sequence. */ -template< - bool __stable, - bool __sentinels, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Compare> - _RAIter3 - __sequential_multiway_merge( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - const typename std::iterator_traits<typename std::iterator_traits< - _RAIterIterator>::value_type::first_type>::value_type& - __sentinel, - _DifferenceTp __length, _Compare __comp) - { - _GLIBCXX_CALL(__length) - - typedef _DifferenceTp _DifferenceType; - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; - -#if _GLIBCXX_ASSERTIONS - for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) - { - _GLIBCXX_PARALLEL_ASSERT( - __is_sorted((*__s).first, (*__s).second, __comp)); - } -#endif + _RAIterIterator>::value_type::first_type>::value_type& + __sentinel, + _DifferenceTp __length, + _Compare __comp) + { + _GLIBCXX_CALL(__length) - _DifferenceTp __total_length = 0; - for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) - __total_length += _GLIBCXX_PARALLEL_LENGTH(*__s); + typedef _DifferenceTp _DifferenceType; + typedef std::iterator_traits<_RAIterIterator> _TraitsType; + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; - __length = std::min<_DifferenceTp>(__length, __total_length); + _RAIter3 __target_end; - if(__length == 0) - return __target; + for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) + // Move the sequence ends to the sentinel. This has the + // effect that the sentinel appears to be within the sequence. Then, + // we can use the unguarded variant if we merge out as many + // non-sentinel elements as we have. + ++((*__s).second); - _RAIter3 __return_target = __target; - int __k = static_cast<int>(__seqs_end - __seqs_begin); + __target_end = multiway_merge_loser_tree_unguarded<UnguardedLoserTree> + (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); - switch (__k) - { - case 0: - break; - case 1: - __return_target = std::copy(__seqs_begin[0].first, - __seqs_begin[0].first + __length, - __target); - __seqs_begin[0].first += __length; - break; - case 2: - __return_target = __merge_advance(__seqs_begin[0].first, - __seqs_begin[0].second, - __seqs_begin[1].first, - __seqs_begin[1].second, - __target, __length, __comp); - break; - case 3: - __return_target = __multiway_merge_3_variant_sentinel_switch< - __sentinels - , _RAIterIterator - , _RAIter3 - , _DifferenceTp - , _Compare>()(__seqs_begin, __seqs_end, __target, __length, __comp); - break; - case 4: - __return_target = __multiway_merge_4_variant_sentinel_switch< - __sentinels - , _RAIterIterator - , _RAIter3 - , _DifferenceTp - , _Compare>()(__seqs_begin, __seqs_end, __target, __length, __comp); - break; - default: - __return_target = __multiway_merge_k_variant_sentinel_switch< - __sentinels - , __stable - , _RAIterIterator - , _RAIter3 - , _DifferenceTp - , _Compare>()(__seqs_begin, __seqs_end, __target, __sentinel, - __length, __comp); - break; - } #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT( - __is_sorted(__target, __target + __length, __comp)); + _GLIBCXX_PARALLEL_ASSERT(__target_end == __target + __length); + _GLIBCXX_PARALLEL_ASSERT(__is_sorted(__target, __target_end, __comp)); #endif - return __return_target; - } + // Restore the sequence ends so the sentinels are not contained in the + // sequence any more (see comment in loop above). + for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) + --((*__s).second); -/** - * @brief Stable sorting functor. - * - * Used to reduce code instanciation in multiway_merge_sampling_splitting. - */ -template<bool __stable, class _RAIter, class _StrictWeakOrdering> -struct _SamplingSorter -{ - void operator()(_RAIter __first, _RAIter __last, - _StrictWeakOrdering __comp) - { __gnu_sequential::stable_sort(__first, __last, __comp); } -}; - -/** - * @brief Non-__stable sorting functor. - * - * Used to reduce code instantiation in multiway_merge_sampling_splitting. - */ -template<class _RAIter, class _StrictWeakOrdering> -struct _SamplingSorter<false, _RAIter, _StrictWeakOrdering> -{ - void operator()(_RAIter __first, _RAIter __last, - _StrictWeakOrdering __comp) - { __gnu_sequential::sort(__first, __last, __comp); } -}; - -/** - * @brief Sampling based splitting for parallel multiway-merge routine. - */ -template< - bool __stable - , typename _RAIterIterator - , typename _Compare - , typename _DifferenceType> -void multiway_merge_sampling_splitting( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _DifferenceType __length, _DifferenceType __total_length, _Compare __comp, - std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) -{ - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename std::iterator_traits<_RAIter1>::value_type - _ValueType; + return __target_end; + } - // __k sequences. - int __k = static_cast<int>(__seqs_end - __seqs_begin); + /** + * @brief Traits for determining whether the loser tree should + * use pointers or copies. + * + * The field "_M_use_pointer" is used to determine whether to use pointers + * in he loser trees or whether to copy the values into the loser tree. + * + * The default behavior is to use pointers if the data type is 4 times as + * big as the pointer to it. + * + * Specialize for your data type to customize the behavior. + * + * Example: + * + * template<> + * struct _LoserTreeTraits<int> + * { static const bool _M_use_pointer = false; }; + * + * template<> + * struct _LoserTreeTraits<heavyweight_type> + * { static const bool _M_use_pointer = true; }; + * + * @param _Tp type to give the loser tree traits for. + */ + template <typename _Tp> + struct _LoserTreeTraits + { + /** + * @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 + * times as big as the pointer to it. + */ + static const bool _M_use_pointer = (sizeof(_Tp) > 4 * sizeof(_Tp*)); + }; - int __num_threads = omp_get_num_threads(); + /** + * @brief Switch for 3-way merging with __sentinels turned off. + * + * Note that 3-way merging is always stable! + */ + template<bool __sentinels /*default == false*/, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + struct __multiway_merge_3_variant_sentinel_switch + { + _RAIter3 + operator()(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _DifferenceTp __length, _Compare __comp) + { return multiway_merge_3_variant<_GuardedIterator> + (__seqs_begin, __seqs_end, __target, __length, __comp); } + }; + + /** + * @brief Switch for 3-way merging with __sentinels turned on. + * + * Note that 3-way merging is always stable! + */ + template<typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + struct __multiway_merge_3_variant_sentinel_switch<true, _RAIterIterator, + _RAIter3, _DifferenceTp, + _Compare> + { + _RAIter3 + operator()(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _DifferenceTp __length, _Compare __comp) + { return multiway_merge_3_variant<_UnguardedIterator> + (__seqs_begin, __seqs_end, __target, __length, __comp); } + }; + + /** + * @brief Switch for 4-way merging with __sentinels turned off. + * + * Note that 4-way merging is always stable! + */ + template<bool __sentinels /*default == false*/, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + struct __multiway_merge_4_variant_sentinel_switch + { + _RAIter3 + operator()(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _DifferenceTp __length, _Compare __comp) + { return multiway_merge_4_variant<_GuardedIterator> + (__seqs_begin, __seqs_end, __target, __length, __comp); } + }; - _DifferenceType __num_samples = - __gnu_parallel::_Settings::get().merge_oversampling * __num_threads; + /** + * @brief Switch for 4-way merging with __sentinels turned on. + * + * Note that 4-way merging is always stable! + */ + template<typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + struct __multiway_merge_4_variant_sentinel_switch<true, _RAIterIterator, + _RAIter3, _DifferenceTp, + _Compare> + { + _RAIter3 + operator()(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _DifferenceTp __length, _Compare __comp) + { return multiway_merge_4_variant<_UnguardedIterator> + (__seqs_begin, __seqs_end, __target, __length, __comp); } + }; - _ValueType* __samples = static_cast<_ValueType*>( - ::operator new(sizeof(_ValueType) * __k * __num_samples)); - // Sample. - for (int __s = 0; __s < __k; ++__s) - for (_DifferenceType __i = 0; __i < __num_samples; ++__i) + /** + * @brief Switch for k-way merging with __sentinels turned on. + */ + template<bool __sentinels, + bool __stable, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + struct __multiway_merge_k_variant_sentinel_switch + { + _RAIter3 + operator()(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + const typename std::iterator_traits<typename std::iterator_traits< + _RAIterIterator>::value_type::first_type>::value_type& + __sentinel, + _DifferenceTp __length, _Compare __comp) { - _DifferenceType sample_index = - static_cast<_DifferenceType>( - _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__s]) - * (double(__i + 1) / (__num_samples + 1)) - * (double(__length) / __total_length)); - new(&(__samples[__s * __num_samples + __i])) - _ValueType(__seqs_begin[__s].first[sample_index]); + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; + + return multiway_merge_loser_tree_sentinel< + typename __gnu_cxx::__conditional_type< + _LoserTreeTraits<_ValueType>::_M_use_pointer, + _LoserTreePointerUnguarded<__stable, _ValueType, _Compare>, + _LoserTreeUnguarded<__stable, _ValueType, _Compare> + >::__type> + (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); } + }; - // Sort stable or non-stable, depending on value of template parameter - // "__stable". - _SamplingSorter<__stable, _ValueType*, _Compare>()( - __samples, __samples + (__num_samples * __k), __comp); - - for (int __slab = 0; __slab < __num_threads; ++__slab) - // For each slab / processor. - for (int __seq = 0; __seq < __k; ++__seq) + /** + * @brief Switch for k-way merging with __sentinels turned off. + */ + template<bool __stable, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + struct __multiway_merge_k_variant_sentinel_switch<false, __stable, + _RAIterIterator, _RAIter3, + _DifferenceTp, _Compare> + { + _RAIter3 + operator()(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + const typename std::iterator_traits<typename std::iterator_traits< + _RAIterIterator>::value_type::first_type>::value_type& + __sentinel, + _DifferenceTp __length, _Compare __comp) { - // For each sequence. - if (__slab > 0) - __pieces[__slab][__seq].first = - std::upper_bound( - __seqs_begin[__seq].first, - __seqs_begin[__seq].second, - __samples[__num_samples * __k * __slab / __num_threads], - __comp) - - __seqs_begin[__seq].first; - else - // Absolute beginning. - __pieces[__slab][__seq].first = 0; - if ((__slab + 1) < __num_threads) - __pieces[__slab][__seq].second = - std::upper_bound( - __seqs_begin[__seq].first, - __seqs_begin[__seq].second, - __samples[__num_samples * __k * (__slab + 1) / - __num_threads], __comp) - - __seqs_begin[__seq].first; - else - // Absolute end. - __pieces[__slab][__seq].second - = _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]); + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; + + return multiway_merge_loser_tree< + typename __gnu_cxx::__conditional_type< + _LoserTreeTraits<_ValueType>::_M_use_pointer, + _LoserTreePointer<__stable, _ValueType, _Compare>, + _LoserTree<__stable, _ValueType, _Compare> + >::__type >(__seqs_begin, __seqs_end, __target, __length, __comp); } - ::operator delete(__samples); -} - -/** - * @brief Exact splitting for parallel multiway-merge routine. - * - * None of the passed sequences may be empty. - */ -template< - bool __stable - , typename _RAIterIterator - , typename _Compare - , typename _DifferenceType> -void multiway_merge_exact_splitting( - _RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _DifferenceType __length, _DifferenceType __total_length, _Compare __comp, - std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) -{ - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; + }; + + /** @brief Sequential multi-way merging switch. + * + * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor and + * runtime settings. + * @param __seqs_begin Begin iterator of iterator pair input sequence. + * @param __seqs_end End iterator of iterator pair input sequence. + * @param __target Begin iterator of output sequence. + * @param __comp Comparator. + * @param __length Maximum length to merge, possibly larger than the + * number of elements available. + * @param __stable Stable merging incurs a performance penalty. + * @param __sentinel The sequences have __a __sentinel element. + * @return End iterator of output sequence. */ + template<bool __stable, + bool __sentinels, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Compare> + _RAIter3 + __sequential_multiway_merge(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + const typename std::iterator_traits<typename std::iterator_traits< + _RAIterIterator>::value_type::first_type>::value_type& + __sentinel, + _DifferenceTp __length, _Compare __comp) + { + _GLIBCXX_CALL(__length) + + typedef _DifferenceTp _DifferenceType; + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; + +#if _GLIBCXX_ASSERTIONS + for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) + { + _GLIBCXX_PARALLEL_ASSERT(__is_sorted((*__s).first, + (*__s).second, __comp)); + } +#endif - const bool __tight = (__total_length == __length); + _DifferenceTp __total_length = 0; + for (_RAIterIterator __s = __seqs_begin; __s != __seqs_end; ++__s) + __total_length += _GLIBCXX_PARALLEL_LENGTH(*__s); - // __k sequences. - const int __k = static_cast<int>(__seqs_end - __seqs_begin); + __length = std::min<_DifferenceTp>(__length, __total_length); - const int __num_threads = omp_get_num_threads(); + if(__length == 0) + return __target; - // (Settings::multiway_merge_splitting == __gnu_parallel::_Settings::EXACT). - std::vector<_RAIter1>* __offsets = - new std::vector<_RAIter1>[__num_threads]; - std::vector< - std::pair<_RAIter1, _RAIter1> - > __se(__k); + _RAIter3 __return_target = __target; + int __k = static_cast<int>(__seqs_end - __seqs_begin); - copy(__seqs_begin, __seqs_end, __se.begin()); + switch (__k) + { + case 0: + break; + case 1: + __return_target = std::copy(__seqs_begin[0].first, + __seqs_begin[0].first + __length, + __target); + __seqs_begin[0].first += __length; + break; + case 2: + __return_target = __merge_advance(__seqs_begin[0].first, + __seqs_begin[0].second, + __seqs_begin[1].first, + __seqs_begin[1].second, + __target, __length, __comp); + break; + case 3: + __return_target = __multiway_merge_3_variant_sentinel_switch + <__sentinels, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>() + (__seqs_begin, __seqs_end, __target, __length, __comp); + break; + case 4: + __return_target = __multiway_merge_4_variant_sentinel_switch + <__sentinels, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare>() + (__seqs_begin, __seqs_end, __target, __length, __comp); + break; + default: + __return_target = __multiway_merge_k_variant_sentinel_switch + <__sentinels, __stable, _RAIterIterator, _RAIter3, _DifferenceTp, + _Compare>() + (__seqs_begin, __seqs_end, __target, __sentinel, __length, __comp); + break; + } +#if _GLIBCXX_ASSERTIONS + _GLIBCXX_PARALLEL_ASSERT( + __is_sorted(__target, __target + __length, __comp)); +#endif - _DifferenceType* __borders = - new _DifferenceType[__num_threads + 1]; - equally_split(__length, __num_threads, __borders); + return __return_target; + } - for (int __s = 0; __s < (__num_threads - 1); ++__s) + /** + * @brief Stable sorting functor. + * + * Used to reduce code instanciation in multiway_merge_sampling_splitting. + */ + template<bool __stable, class _RAIter, class _StrictWeakOrdering> + struct _SamplingSorter { - __offsets[__s].resize(__k); - multiseq_partition( - __se.begin(), __se.end(), __borders[__s + 1], - __offsets[__s].begin(), __comp); - - // Last one also needed and available. - if (!__tight) - { - __offsets[__num_threads - 1].resize(__k); - multiseq_partition(__se.begin(), __se.end(), - _DifferenceType(__length), - __offsets[__num_threads - 1].begin(), __comp); - } - } - delete[] __borders; + void + operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp) + { __gnu_sequential::stable_sort(__first, __last, __comp); } + }; - for (int __slab = 0; __slab < __num_threads; ++__slab) + /** + * @brief Non-__stable sorting functor. + * + * Used to reduce code instantiation in multiway_merge_sampling_splitting. + */ + template<class _RAIter, class _StrictWeakOrdering> + struct _SamplingSorter<false, _RAIter, _StrictWeakOrdering> { - // For each slab / processor. - for (int __seq = 0; __seq < __k; ++__seq) - { - // For each sequence. - if (__slab == 0) - { - // Absolute beginning. - __pieces[__slab][__seq].first = 0; - } - else - __pieces[__slab][__seq].first = - __pieces[__slab - 1][__seq].second; - if (!__tight || __slab < (__num_threads - 1)) - __pieces[__slab][__seq].second = - __offsets[__slab][__seq] - __seqs_begin[__seq].first; - else - { - // __slab == __num_threads - 1 - __pieces[__slab][__seq].second = - _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]); - } - } + void + operator()(_RAIter __first, _RAIter __last, _StrictWeakOrdering __comp) + { __gnu_sequential::sort(__first, __last, __comp); } + }; + + /** + * @brief Sampling based splitting for parallel multiway-merge routine. + */ + template<bool __stable, + typename _RAIterIterator, + typename _Compare, + typename _DifferenceType> + void + multiway_merge_sampling_splitting(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _DifferenceType __length, + _DifferenceType __total_length, + _Compare __comp, + std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) + { + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename std::iterator_traits<_RAIter1>::value_type + _ValueType; + + // __k sequences. + int __k = static_cast<int>(__seqs_end - __seqs_begin); + + int __num_threads = omp_get_num_threads(); + + _DifferenceType __num_samples = + __gnu_parallel::_Settings::get().merge_oversampling * __num_threads; + + _ValueType* __samples = static_cast<_ValueType*> + (::operator new(sizeof(_ValueType) * __k * __num_samples)); + // Sample. + for (int __s = 0; __s < __k; ++__s) + for (_DifferenceType __i = 0; __i < __num_samples; ++__i) + { + _DifferenceType sample_index = static_cast<_DifferenceType> + (_GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__s]) + * (double(__i + 1) / (__num_samples + 1)) + * (double(__length) / __total_length)); + new(&(__samples[__s * __num_samples + __i])) + _ValueType(__seqs_begin[__s].first[sample_index]); + } + + // Sort stable or non-stable, depending on value of template parameter + // "__stable". + _SamplingSorter<__stable, _ValueType*, _Compare>() + (__samples, __samples + (__num_samples * __k), __comp); + + for (int __slab = 0; __slab < __num_threads; ++__slab) + // For each slab / processor. + for (int __seq = 0; __seq < __k; ++__seq) + { + // For each sequence. + if (__slab > 0) + __pieces[__slab][__seq].first = std::upper_bound + (__seqs_begin[__seq].first, __seqs_begin[__seq].second, + __samples[__num_samples * __k * __slab / __num_threads], + __comp) + - __seqs_begin[__seq].first; + else + // Absolute beginning. + __pieces[__slab][__seq].first = 0; + if ((__slab + 1) < __num_threads) + __pieces[__slab][__seq].second = std::upper_bound + (__seqs_begin[__seq].first, __seqs_begin[__seq].second, + __samples[__num_samples * __k * (__slab + 1) / __num_threads], + __comp) + - __seqs_begin[__seq].first; + else + // Absolute end. + __pieces[__slab][__seq].second = + _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]); + } + ::operator delete(__samples); } - delete[] __offsets; -} - -/** @brief Parallel multi-way merge routine. - * - * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor - * and runtime settings. - * - * Must not be called if the number of sequences is 1. - * - * @param _Splitter functor to split input (either __exact or sampling based) - * - * @param __seqs_begin Begin iterator of iterator pair input sequence. - * @param __seqs_end End iterator of iterator pair input sequence. - * @param __target Begin iterator of output sequence. - * @param __comp Comparator. - * @param __length Maximum length to merge, possibly larger than the - * number of elements available. - * @param __stable Stable merging incurs a performance penalty. - * @param __sentinel Ignored. - * @return End iterator of output sequence. - */ -template< - bool __stable, - bool __sentinels, - typename _RAIterIterator, - typename _RAIter3, - typename _DifferenceTp, - typename _Splitter, - typename _Compare - > - _RAIter3 - parallel_multiway_merge(_RAIterIterator __seqs_begin, - _RAIterIterator __seqs_end, - _RAIter3 __target, - _Splitter __splitter, - _DifferenceTp __length, - _Compare __comp, - _ThreadIndex __num_threads) + + /** + * @brief Exact splitting for parallel multiway-merge routine. + * + * None of the passed sequences may be empty. + */ + template<bool __stable, + typename _RAIterIterator, + typename _Compare, + typename _DifferenceType> + void + multiway_merge_exact_splitting(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _DifferenceType __length, + _DifferenceType __total_length, + _Compare __comp, + std::vector<std::pair<_DifferenceType, _DifferenceType> > *__pieces) { + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + + const bool __tight = (__total_length == __length); + + // __k sequences. + const int __k = static_cast<int>(__seqs_end - __seqs_begin); + + const int __num_threads = omp_get_num_threads(); + + // (Settings::multiway_merge_splitting + // == __gnu_parallel::_Settings::EXACT). + std::vector<_RAIter1>* __offsets = + new std::vector<_RAIter1>[__num_threads]; + std::vector<std::pair<_RAIter1, _RAIter1> > __se(__k); + + copy(__seqs_begin, __seqs_end, __se.begin()); + + _DifferenceType* __borders = + new _DifferenceType[__num_threads + 1]; + equally_split(__length, __num_threads, __borders); + + for (int __s = 0; __s < (__num_threads - 1); ++__s) + { + __offsets[__s].resize(__k); + multiseq_partition(__se.begin(), __se.end(), __borders[__s + 1], + __offsets[__s].begin(), __comp); + + // Last one also needed and available. + if (!__tight) + { + __offsets[__num_threads - 1].resize(__k); + multiseq_partition(__se.begin(), __se.end(), + _DifferenceType(__length), + __offsets[__num_threads - 1].begin(), + __comp); + } + } + delete[] __borders; + + for (int __slab = 0; __slab < __num_threads; ++__slab) + { + // For each slab / processor. + for (int __seq = 0; __seq < __k; ++__seq) + { + // For each sequence. + if (__slab == 0) + { + // Absolute beginning. + __pieces[__slab][__seq].first = 0; + } + else + __pieces[__slab][__seq].first = + __pieces[__slab - 1][__seq].second; + if (!__tight || __slab < (__num_threads - 1)) + __pieces[__slab][__seq].second = + __offsets[__slab][__seq] - __seqs_begin[__seq].first; + else + { + // __slab == __num_threads - 1 + __pieces[__slab][__seq].second = + _GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]); + } + } + } + delete[] __offsets; + } + + /** @brief Parallel multi-way merge routine. + * + * The _GLIBCXX_PARALLEL_DECISION is based on the branching factor + * and runtime settings. + * + * Must not be called if the number of sequences is 1. + * + * @param _Splitter functor to split input (either __exact or sampling based) + * + * @param __seqs_begin Begin iterator of iterator pair input sequence. + * @param __seqs_end End iterator of iterator pair input sequence. + * @param __target Begin iterator of output sequence. + * @param __comp Comparator. + * @param __length Maximum length to merge, possibly larger than the + * number of elements available. + * @param __stable Stable merging incurs a performance penalty. + * @param __sentinel Ignored. + * @return End iterator of output sequence. + */ + template<bool __stable, + bool __sentinels, + typename _RAIterIterator, + typename _RAIter3, + typename _DifferenceTp, + typename _Splitter, + typename _Compare> + _RAIter3 + parallel_multiway_merge(_RAIterIterator __seqs_begin, + _RAIterIterator __seqs_end, + _RAIter3 __target, + _Splitter __splitter, + _DifferenceTp __length, + _Compare __comp, + _ThreadIndex __num_threads) + { #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(__seqs_end - __seqs_begin > 1); + _GLIBCXX_PARALLEL_ASSERT(__seqs_end - __seqs_begin > 1); #endif - _GLIBCXX_CALL(__length) - - typedef _DifferenceTp _DifferenceType; - typedef typename std::iterator_traits<_RAIterIterator> - ::value_type::first_type - _RAIter1; - typedef typename - std::iterator_traits<_RAIter1>::value_type _ValueType; - - // Leave only non-empty sequences. - typedef std::pair<_RAIter1, _RAIter1> seq_type; - seq_type* __ne_seqs = new seq_type[__seqs_end - __seqs_begin]; - int __k = 0; - _DifferenceType __total_length = 0; - for (_RAIterIterator __raii = __seqs_begin; - __raii != __seqs_end; ++__raii) - { - _DifferenceTp __seq_length = _GLIBCXX_PARALLEL_LENGTH(*__raii); - if(__seq_length > 0) - { - __total_length += __seq_length; - __ne_seqs[__k++] = *__raii; - } - } + _GLIBCXX_CALL(__length) + + typedef _DifferenceTp _DifferenceType; + typedef typename std::iterator_traits<_RAIterIterator> + ::value_type::first_type + _RAIter1; + typedef typename + std::iterator_traits<_RAIter1>::value_type _ValueType; + + // Leave only non-empty sequences. + typedef std::pair<_RAIter1, _RAIter1> seq_type; + seq_type* __ne_seqs = new seq_type[__seqs_end - __seqs_begin]; + int __k = 0; + _DifferenceType __total_length = 0; + for (_RAIterIterator __raii = __seqs_begin; + __raii != __seqs_end; ++__raii) + { + _DifferenceTp __seq_length = _GLIBCXX_PARALLEL_LENGTH(*__raii); + if(__seq_length > 0) + { + __total_length += __seq_length; + __ne_seqs[__k++] = *__raii; + } + } - _GLIBCXX_CALL(__total_length) + _GLIBCXX_CALL(__total_length) - __length = std::min<_DifferenceTp>(__length, __total_length); + __length = std::min<_DifferenceTp>(__length, __total_length); - if (__total_length == 0 || __k == 0) - { - delete[] __ne_seqs; - return __target; - } + if (__total_length == 0 || __k == 0) + { + delete[] __ne_seqs; + return __target; + } - std::vector<std::pair<_DifferenceType, _DifferenceType> >* __pieces; + std::vector<std::pair<_DifferenceType, _DifferenceType> >* __pieces; - __num_threads = static_cast<_ThreadIndex> - (std::min<_DifferenceType>(__num_threads, __total_length)); + __num_threads = static_cast<_ThreadIndex> + (std::min<_DifferenceType>(__num_threads, __total_length)); -# pragma omp parallel num_threads (__num_threads) - { +# pragma omp parallel num_threads (__num_threads) + { # pragma omp single - { - __num_threads = omp_get_num_threads(); - // Thread __t will have to merge pieces[__iam][0..__k - 1] - __pieces = new std::vector< - std::pair<_DifferenceType, _DifferenceType> >[__num_threads]; - for (int __s = 0; __s < __num_threads; ++__s) - __pieces[__s].resize(__k); + { + __num_threads = omp_get_num_threads(); + // Thread __t will have to merge pieces[__iam][0..__k - 1] + __pieces = new std::vector< + std::pair<_DifferenceType, _DifferenceType> >[__num_threads]; + for (int __s = 0; __s < __num_threads; ++__s) + __pieces[__s].resize(__k); - _DifferenceType __num_samples = - __gnu_parallel::_Settings::get().merge_oversampling * - __num_threads; + _DifferenceType __num_samples = + __gnu_parallel::_Settings::get().merge_oversampling + * __num_threads; - __splitter(__ne_seqs, __ne_seqs + __k, __length, __total_length, - __comp, __pieces); - } //single + __splitter(__ne_seqs, __ne_seqs + __k, __length, __total_length, + __comp, __pieces); + } //single - _ThreadIndex __iam = omp_get_thread_num(); + _ThreadIndex __iam = omp_get_thread_num(); - _DifferenceType __target_position = 0; + _DifferenceType __target_position = 0; - for (int __c = 0; __c < __k; ++__c) - __target_position += __pieces[__iam][__c].first; + for (int __c = 0; __c < __k; ++__c) + __target_position += __pieces[__iam][__c].first; - seq_type* __chunks = new seq_type[__k]; + seq_type* __chunks = new seq_type[__k]; - for (int __s = 0; __s < __k; ++__s) - { - __chunks[__s] = std::make_pair( - __ne_seqs[__s].first + __pieces[__iam][__s].first, - __ne_seqs[__s].first + __pieces[__iam][__s].second); - } + for (int __s = 0; __s < __k; ++__s) + __chunks[__s] = std::make_pair(__ne_seqs[__s].first + + __pieces[__iam][__s].first, + __ne_seqs[__s].first + + __pieces[__iam][__s].second); - if(__length > __target_position) - __sequential_multiway_merge<__stable, __sentinels>( - __chunks, __chunks + __k, __target + __target_position, - *(__seqs_begin->second), __length - __target_position, __comp); + if(__length > __target_position) + __sequential_multiway_merge<__stable, __sentinels> + (__chunks, __chunks + __k, __target + __target_position, + *(__seqs_begin->second), __length - __target_position, __comp); - delete[] __chunks; - } // parallel + delete[] __chunks; + } // parallel #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT( - __is_sorted(__target, __target + __length, __comp)); + _GLIBCXX_PARALLEL_ASSERT( + __is_sorted(__target, __target + __length, __comp)); #endif - __k = 0; - // Update ends of sequences. - for (_RAIterIterator __raii = __seqs_begin; - __raii != __seqs_end; ++__raii) - { - _DifferenceTp __length = _GLIBCXX_PARALLEL_LENGTH(*__raii); - if(__length > 0) - (*__raii).first += __pieces[__num_threads - 1][__k++].second; - } + __k = 0; + // Update ends of sequences. + for (_RAIterIterator __raii = __seqs_begin; + __raii != __seqs_end; ++__raii) + { + _DifferenceTp __length = _GLIBCXX_PARALLEL_LENGTH(*__raii); + if(__length > 0) + (*__raii).first += __pieces[__num_threads - 1][__k++].second; + } - delete[] __pieces; - delete[] __ne_seqs; + delete[] __pieces; + delete[] __ne_seqs; - return __target + __length; - } + return __target + __length; + } -/** - * @brief Multiway Merge Frontend. - * - * Merge the sequences specified by seqs_begin and __seqs_end into - * __target. __seqs_begin and __seqs_end must point to a sequence of - * pairs. These pairs must contain an iterator to the beginning - * of a sequence in their first entry and an iterator the _M_end of - * the same sequence in their second entry. - * - * Ties are broken arbitrarily. See stable_multiway_merge for a variant - * that breaks ties by sequence number but is slower. - * - * The first entries of the pairs (i.e. the begin iterators) will be moved - * forward. - * - * The output sequence has to provide enough space for all elements - * that are written to it. - * - * This function will merge the input sequences: - * - * - not stable - * - parallel, depending on the input size and Settings - * - using sampling for splitting - * - not using sentinels - * - * Example: - * - * <pre> - * int sequences[10][10]; - * for (int __i = 0; __i < 10; ++__i) - * for (int __j = 0; __i < 10; ++__j) - * sequences[__i][__j] = __j; - * - * int __out[33]; - * std::vector<std::pair<int*> > seqs; - * for (int __i = 0; __i < 10; ++__i) - * { seqs.push(std::make_pair<int*>(sequences[__i], sequences[__i] + 10)) } - * - * multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33); - * </pre> - * - * @see stable_multiway_merge - * - * @pre All input sequences must be sorted. - * @pre Target must provide enough space to merge out length elements or - * the number of elements in all sequences, whichever is smaller. - * - * @post [__target, return __value) contains merged __elements from the - * input sequences. - * @post return __value - __target = min(__length, number of elements in all - * sequences). - * - * @param _RAIterPairIterator iterator over sequence - * of pairs of iterators - * @param _RAIterOut iterator over target sequence - * @param _DifferenceTp difference type for the sequence - * @param _Compare strict weak ordering type to compare elements - * in sequences - * - * @param __seqs_begin __begin of sequence __sequence - * @param __seqs_end _M_end of sequence __sequence - * @param __target target sequence to merge to. - * @param __comp strict weak ordering to use for element comparison. - * @param __length Maximum length to merge, possibly larger than the - * number of elements available. - * - * @return _M_end iterator of output sequence - */ -// multiway_merge -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::sequential_tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) - - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; - - // Execute multiway merge *sequentially*. - return __sequential_multiway_merge - </* __stable = */ false, /* __sentinels = */ false> - (__seqs_begin, __seqs_end, __target, - *(__seqs_begin->second), __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::exact_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + /** + * @brief Multiway Merge Frontend. + * + * Merge the sequences specified by seqs_begin and __seqs_end into + * __target. __seqs_begin and __seqs_end must point to a sequence of + * pairs. These pairs must contain an iterator to the beginning + * of a sequence in their first entry and an iterator the _M_end of + * the same sequence in their second entry. + * + * Ties are broken arbitrarily. See stable_multiway_merge for a variant + * that breaks ties by sequence number but is slower. + * + * The first entries of the pairs (i.e. the begin iterators) will be moved + * forward. + * + * The output sequence has to provide enough space for all elements + * that are written to it. + * + * This function will merge the input sequences: + * + * - not stable + * - parallel, depending on the input size and Settings + * - using sampling for splitting + * - not using sentinels + * + * Example: + * + * <pre> + * int sequences[10][10]; + * for (int __i = 0; __i < 10; ++__i) + * for (int __j = 0; __i < 10; ++__j) + * sequences[__i][__j] = __j; + * + * int __out[33]; + * std::vector<std::pair<int*> > seqs; + * for (int __i = 0; __i < 10; ++__i) + * { seqs.push(std::make_pair<int*>(sequences[__i], + * sequences[__i] + 10)) } + * + * multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33); + * </pre> + * + * @see stable_multiway_merge + * + * @pre All input sequences must be sorted. + * @pre Target must provide enough space to merge out length elements or + * the number of elements in all sequences, whichever is smaller. + * + * @post [__target, return __value) contains merged __elements from the + * input sequences. + * @post return __value - __target = min(__length, number of elements in all + * sequences). + * + * @param _RAIterPairIterator iterator over sequence + * of pairs of iterators + * @param _RAIterOut iterator over target sequence + * @param _DifferenceTp difference type for the sequence + * @param _Compare strict weak ordering type to compare elements + * in sequences + * + * @param __seqs_begin __begin of sequence __sequence + * @param __seqs_end _M_end of sequence __sequence + * @param __target target sequence to merge to. + * @param __comp strict weak ordering to use for element comparison. + * @param __length Maximum length to merge, possibly larger than the + * number of elements available. + * + * @return _M_end iterator of output sequence + */ + // multiway_merge + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::sequential_tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ false, /* __sentinels = */ false>( - __seqs_begin, __seqs_end, __target, - multiway_merge_exact_splitting</* __stable = */ false, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else + // Execute multiway merge *sequentially*. return __sequential_multiway_merge - </* __stable = */ false, /* __sentinels = */ false>( - __seqs_begin, __seqs_end, __target, *(__seqs_begin->second), - __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::sampling_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + </* __stable = */ false, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::exact_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((_SequenceIndex)__length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* __stable = */ false, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + multiway_merge_exact_splitting</* __stable = */ false, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */ false, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ false, /* __sentinels = */ false>( - __seqs_begin, __seqs_end, - __target, - multiway_merge_exact_splitting</* __stable = */ false, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else - return __sequential_multiway_merge - </* __stable = */ false, /* __sentinels = */ false>( - __seqs_begin, __seqs_end, - __target, *(__seqs_begin->second), __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , parallel_tag __tag = parallel_tag(0)) -{ - return multiway_merge(__seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , default_parallel_tag __tag) -{ - return multiway_merge(__seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} - -// stable_multiway_merge -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::sequential_tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::sampling_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((_SequenceIndex)__length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* __stable = */ false, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + multiway_merge_exact_splitting</* __stable = */ false, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */ false, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + parallel_tag __tag = parallel_tag(0)) + { return multiway_merge(__seqs_begin, __seqs_end, __target, __length, + __comp, exact_tag(__tag.__get_num_threads())); } + + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + default_parallel_tag __tag) + { return multiway_merge(__seqs_begin, __seqs_end, __target, __length, + __comp, exact_tag(__tag.__get_num_threads())); } + + // stable_multiway_merge + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::sequential_tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) - // Execute multiway merge *sequentially*. - return __sequential_multiway_merge - </* __stable = */ true, /* __sentinels = */ false> - (__seqs_begin, __seqs_end, __target, *(__seqs_begin->second), __length, - __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::exact_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // Execute multiway merge *sequentially*. + return __sequential_multiway_merge + </* __stable = */ true, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ true, /* __sentinels = */ false>( - __seqs_begin, __seqs_end, - __target, - multiway_merge_exact_splitting</* __stable = */ true, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else - return __sequential_multiway_merge</* __stable = */ true, - /* __sentinels = */ false>( - __seqs_begin, __seqs_end, - __target, *(__seqs_begin->second), __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , sampling_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::exact_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((_SequenceIndex)__length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* __stable = */ true, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + multiway_merge_exact_splitting</* __stable = */ true, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */ true, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + sampling_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((_SequenceIndex)__length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* __stable = */ true, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + multiway_merge_sampling_splitting</* __stable = */ true, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */ true, /* __sentinels = */ false> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ true, /* __sentinels = */ false>( - __seqs_begin, __seqs_end, - __target, - multiway_merge_sampling_splitting</* __stable = */ true, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else - return __sequential_multiway_merge - </* __stable = */ true, /* __sentinels = */ false>( - __seqs_begin, __seqs_end, - __target, *(__seqs_begin->second), __length, __comp); -} - - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , parallel_tag __tag = parallel_tag(0)) -{ - return stable_multiway_merge( - __seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , default_parallel_tag __tag) -{ - return stable_multiway_merge( - __seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} - -/** - * @brief Multiway Merge Frontend. - * - * Merge the sequences specified by seqs_begin and __seqs_end into - * __target. __seqs_begin and __seqs_end must point to a sequence of - * pairs. These pairs must contain an iterator to the beginning - * of a sequence in their first entry and an iterator the _M_end of - * the same sequence in their second entry. - * - * Ties are broken arbitrarily. See stable_multiway_merge for a variant - * that breaks ties by sequence number but is slower. - * - * The first entries of the pairs (i.e. the begin iterators) will be moved - * forward accordingly. - * - * The output sequence has to provide enough space for all elements - * that are written to it. - * - * This function will merge the input sequences: - * - * - not stable - * - parallel, depending on the input size and Settings - * - using sampling for splitting - * - using sentinels - * - * You have to take care that the element the _M_end iterator points to is - * readable and contains a value that is greater than any other non-sentinel - * value in all sequences. - * - * Example: - * - * <pre> - * int sequences[10][11]; - * for (int __i = 0; __i < 10; ++__i) - * for (int __j = 0; __i < 11; ++__j) - * sequences[__i][__j] = __j; // __last one is sentinel! - * - * int __out[33]; - * std::vector<std::pair<int*> > seqs; - * for (int __i = 0; __i < 10; ++__i) - * { seqs.push(std::make_pair<int*>(sequences[__i], sequences[__i] + 10)) } - * - * multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33); - * </pre> - * - * @pre All input sequences must be sorted. - * @pre Target must provide enough space to merge out length elements or - * the number of elements in all sequences, whichever is smaller. - * @pre For each @__c __i, @__c __seqs_begin[__i].second must be the end - * marker of the sequence, but also reference the one more __sentinel - * element. - * - * @post [__target, return __value) contains merged __elements from the - * input sequences. - * @post return __value - __target = min(__length, number of elements in all - * sequences). - * - * @see stable_multiway_merge_sentinels - * - * @param _RAIterPairIterator iterator over sequence - * of pairs of iterators - * @param _RAIterOut iterator over target sequence - * @param _DifferenceTp difference type for the sequence - * @param _Compare strict weak ordering type to compare elements - * in sequences - * - * @param __seqs_begin __begin of sequence __sequence - * @param __seqs_end _M_end of sequence __sequence - * @param __target target sequence to merge to. - * @param __comp strict weak ordering to use for element comparison. - * @param __length Maximum length to merge, possibly larger than the - * number of elements available. - * - * @return _M_end iterator of output sequence - */ -// multiway_merge_sentinels -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::sequential_tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + parallel_tag __tag = parallel_tag(0)) + { + return stable_multiway_merge + (__seqs_begin, __seqs_end, __target, __length, __comp, + exact_tag(__tag.__get_num_threads())); + } - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + default_parallel_tag __tag) + { + return stable_multiway_merge + (__seqs_begin, __seqs_end, __target, __length, __comp, + exact_tag(__tag.__get_num_threads())); + } - // Execute multiway merge *sequentially*. - return __sequential_multiway_merge - </* __stable = */ false, /* __sentinels = */ true> - (__seqs_begin, __seqs_end, - __target, *(__seqs_begin->second), __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::exact_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + /** + * @brief Multiway Merge Frontend. + * + * Merge the sequences specified by seqs_begin and __seqs_end into + * __target. __seqs_begin and __seqs_end must point to a sequence of + * pairs. These pairs must contain an iterator to the beginning + * of a sequence in their first entry and an iterator the _M_end of + * the same sequence in their second entry. + * + * Ties are broken arbitrarily. See stable_multiway_merge for a variant + * that breaks ties by sequence number but is slower. + * + * The first entries of the pairs (i.e. the begin iterators) will be moved + * forward accordingly. + * + * The output sequence has to provide enough space for all elements + * that are written to it. + * + * This function will merge the input sequences: + * + * - not stable + * - parallel, depending on the input size and Settings + * - using sampling for splitting + * - using sentinels + * + * You have to take care that the element the _M_end iterator points to is + * readable and contains a value that is greater than any other non-sentinel + * value in all sequences. + * + * Example: + * + * <pre> + * int sequences[10][11]; + * for (int __i = 0; __i < 10; ++__i) + * for (int __j = 0; __i < 11; ++__j) + * sequences[__i][__j] = __j; // __last one is sentinel! + * + * int __out[33]; + * std::vector<std::pair<int*> > seqs; + * for (int __i = 0; __i < 10; ++__i) + * { seqs.push(std::make_pair<int*>(sequences[__i], + * sequences[__i] + 10)) } + * + * multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33); + * </pre> + * + * @pre All input sequences must be sorted. + * @pre Target must provide enough space to merge out length elements or + * the number of elements in all sequences, whichever is smaller. + * @pre For each @c __i, @c __seqs_begin[__i].second must be the end + * marker of the sequence, but also reference the one more __sentinel + * element. + * + * @post [__target, return __value) contains merged __elements from the + * input sequences. + * @post return __value - __target = min(__length, number of elements in all + * sequences). + * + * @see stable_multiway_merge_sentinels + * + * @param _RAIterPairIterator iterator over sequence + * of pairs of iterators + * @param _RAIterOut iterator over target sequence + * @param _DifferenceTp difference type for the sequence + * @param _Compare strict weak ordering type to compare elements + * in sequences + * + * @param __seqs_begin __begin of sequence __sequence + * @param __seqs_end _M_end of sequence __sequence + * @param __target target sequence to merge to. + * @param __comp strict weak ordering to use for element comparison. + * @param __length Maximum length to merge, possibly larger than the + * number of elements available. + * + * @return _M_end iterator of output sequence + */ + // multiway_merge_sentinels + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::sequential_tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ false, /* __sentinels = */ true>( - __seqs_begin, __seqs_end, - __target, - multiway_merge_exact_splitting</* __stable = */ false, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else + // Execute multiway merge *sequentially*. return __sequential_multiway_merge - </* __stable = */ false, /* __sentinels = */ true>( - __seqs_begin, __seqs_end, - __target, *(__seqs_begin->second), __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , sampling_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + </* __stable = */ false, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, + __target, *(__seqs_begin->second), __length, __comp); + } - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::exact_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((_SequenceIndex)__length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* __stable = */ false, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + multiway_merge_exact_splitting</* __stable = */ false, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */ false, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ false, /* __sentinels = */ true> - (__seqs_begin, __seqs_end, __target, - multiway_merge_sampling_splitting</* __stable = */ false, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else - return __sequential_multiway_merge - </* __stable = */false, /* __sentinels = */ true>( - __seqs_begin, __seqs_end, - __target, *(__seqs_begin->second), __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , parallel_tag __tag = parallel_tag(0)) -{ - return multiway_merge_sentinels( - __seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , default_parallel_tag __tag) -{ - return multiway_merge_sentinels( - __seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} - -// stable_multiway_merge_sentinels -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::sequential_tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + sampling_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((_SequenceIndex)__length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* __stable = */ false, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + multiway_merge_sampling_splitting</* __stable = */ false, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */false, /* __sentinels = */ true>( + __seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + parallel_tag __tag = parallel_tag(0)) + { + return multiway_merge_sentinels + (__seqs_begin, __seqs_end, __target, __length, __comp, + exact_tag(__tag.__get_num_threads())); + } - // Execute multiway merge *sequentially*. - return __sequential_multiway_merge - </* __stable = */ true, /* __sentinels = */ true> - (__seqs_begin, __seqs_end, __target, *(__seqs_begin->second), __length, - __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , __gnu_parallel::exact_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + default_parallel_tag __tag) + { + return multiway_merge_sentinels + (__seqs_begin, __seqs_end, __target, __length, __comp, + exact_tag(__tag.__get_num_threads())); + } - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // stable_multiway_merge_sentinels + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::sequential_tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ true, /* __sentinels = */ true>( - __seqs_begin, __seqs_end, - __target, - multiway_merge_exact_splitting</* __stable = */ true, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else - return __sequential_multiway_merge - </* __stable = */ true, /* __sentinels = */ true>( - __seqs_begin, __seqs_end, __target, *(__seqs_begin->second), - __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , sampling_tag __tag) -{ - typedef _DifferenceTp _DifferenceType; - _GLIBCXX_CALL(__seqs_end - __seqs_begin) + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; - // catch special case: no sequences - if (__seqs_begin == __seqs_end) - return __target; + // Execute multiway merge *sequentially*. + return __sequential_multiway_merge + </* __stable = */ true, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((__seqs_end - __seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((__seqs_end - __seqs_begin) >= + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + __gnu_parallel::exact_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((_SequenceIndex)__length >= + && ((_SequenceIndex)__length >= __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* __stable = */ true, /* __sentinels = */ true>( - __seqs_begin, __seqs_end, - __target, - multiway_merge_sampling_splitting</* __stable = */ true, - typename std::iterator_traits<_RAIterPairIterator> - ::value_type*, _Compare, _DifferenceTp>, - static_cast<_DifferenceType>(__length), __comp, - __tag.__get_num_threads()); - else - return __sequential_multiway_merge - </* __stable = */ true, /* __sentinels = */ true>( - __seqs_begin, __seqs_end, - __target, *(__seqs_begin->second), __length, __comp); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , parallel_tag __tag = parallel_tag(0)) -{ - return stable_multiway_merge_sentinels( - __seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} - -// public interface -template< - typename _RAIterPairIterator - , typename _RAIterOut - , typename _DifferenceTp - , typename _Compare> -_RAIterOut -stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin - , _RAIterPairIterator __seqs_end - , _RAIterOut __target - , _DifferenceTp __length, _Compare __comp - , default_parallel_tag __tag) -{ - return stable_multiway_merge_sentinels( - __seqs_begin, __seqs_end, __target, __length, __comp, - exact_tag(__tag.__get_num_threads())); -} + return parallel_multiway_merge + </* __stable = */ true, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + multiway_merge_exact_splitting</* __stable = */ true, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */ true, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } + + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, + _Compare __comp, + sampling_tag __tag) + { + typedef _DifferenceTp _DifferenceType; + _GLIBCXX_CALL(__seqs_end - __seqs_begin) + + // catch special case: no sequences + if (__seqs_begin == __seqs_end) + return __target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((__seqs_end - __seqs_begin > 1) + && _GLIBCXX_PARALLEL_CONDITION( + ((__seqs_end - __seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((_SequenceIndex)__length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* __stable = */ true, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + multiway_merge_sampling_splitting</* __stable = */ true, + typename std::iterator_traits<_RAIterPairIterator> + ::value_type*, _Compare, _DifferenceTp>, + static_cast<_DifferenceType>(__length), __comp, + __tag.__get_num_threads()); + else + return __sequential_multiway_merge + </* __stable = */ true, /* __sentinels = */ true> + (__seqs_begin, __seqs_end, __target, + *(__seqs_begin->second), __length, __comp); + } + + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, + _Compare __comp, + parallel_tag __tag = parallel_tag(0)) + { + return stable_multiway_merge_sentinels + (__seqs_begin, __seqs_end, __target, __length, __comp, + exact_tag(__tag.__get_num_threads())); + } + // public interface + template<typename _RAIterPairIterator, + typename _RAIterOut, + typename _DifferenceTp, + typename _Compare> + _RAIterOut + stable_multiway_merge_sentinels(_RAIterPairIterator __seqs_begin, + _RAIterPairIterator __seqs_end, + _RAIterOut __target, + _DifferenceTp __length, _Compare __comp, + default_parallel_tag __tag) + { + return stable_multiway_merge_sentinels + (__seqs_begin, __seqs_end, __target, __length, __comp, + exact_tag(__tag.__get_num_threads())); + } }; // namespace __gnu_parallel #endif /* _GLIBCXX_PARALLEL_MULTIWAY_MERGE_H */ diff --git a/libstdc++-v3/include/parallel/multiway_mergesort.h b/libstdc++-v3/include/parallel/multiway_mergesort.h index c7f10ae7511..f2bb6fbc30d 100644 --- a/libstdc++-v3/include/parallel/multiway_mergesort.h +++ b/libstdc++-v3/include/parallel/multiway_mergesort.h @@ -41,451 +41,434 @@ namespace __gnu_parallel { + /** @brief Subsequence description. */ + template<typename _DifferenceTp> + struct _Piece + { + typedef _DifferenceTp _DifferenceType; -/** @brief Subsequence description. */ -template<typename _DifferenceTp> - struct _Piece - { - typedef _DifferenceTp _DifferenceType; + /** @brief Begin of subsequence. */ + _DifferenceType _M_begin; - /** @brief Begin of subsequence. */ - _DifferenceType _M_begin; + /** @brief End of subsequence. */ + _DifferenceType _M_end; + }; - /** @brief End of subsequence. */ - _DifferenceType _M_end; - }; + /** @brief Data accessed by all 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 Data accessed by all 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 Number of threads involved. */ + _ThreadIndex _M_num_threads; -/** @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]; - } + /** @brief Input __begin. */ + _RAIter _M_source; -# pragma omp barrier + /** @brief Start indices, per thread. */ + _DifferenceType* _M_starts; - 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 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 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 + /** + * @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 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 - __gnu_sequential::sort(__sd->_M_samples, - __sd->_M_samples - + (__num_samples * __sd->_M_num_threads), - __comp); + equally_split(__sd->_M_starts[__iam + 1] - __sd->_M_starts[__iam], + __num_samples + 1, __es); -# 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) - { - // For each sequence. - if (__num_samples * __iam > 0) - __sd->_M_pieces[__iam][__s]._M_begin = + /** @brief Split consistently. */ + template<bool __exact, typename _RAIter, + typename _Compare, typename _SortingPlacesIterator> + struct _SplitConsistently + { }; + + /** @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> __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], __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 + = __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], - __sd->_M_temporary[__s] - + (__sd->_M_starts[__s + 1] - __sd->_M_starts[__s]), - __sd->_M_samples[__num_samples * __iam], - __comp) + __sd->_M_temporary[__s] + + (__sd->_M_starts[__s + 1] + - __sd->_M_starts[__s]), + __sd->_M_samples[__num_samples * __iam], + __comp) - __sd->_M_temporary[__s]; - else - // Absolute beginning. - __sd->_M_pieces[__iam][__s]._M_begin = 0; + else + // Absolute beginning. + __sd->_M_pieces[__iam][__s]._M_begin = 0; - if ((__num_samples * (__iam + 1)) < - (__num_samples * __sd->_M_num_threads)) - __sd->_M_pieces[__iam][__s]._M_end = + if ((__num_samples * (__iam + 1)) < + (__num_samples * __sd->_M_num_threads)) + __sd->_M_pieces[__iam][__s]._M_end = std::lower_bound(__sd->_M_temporary[__s], - __sd->_M_temporary[__s] - + (__sd->_M_starts[__s + 1] - __sd->_M_starts[__s]), - __sd->_M_samples[__num_samples * (__iam + 1)], - __comp) + __sd->_M_temporary[__s] + + (__sd->_M_starts[__s + 1] + - __sd->_M_starts[__s]), + __sd->_M_samples[__num_samples * (__iam + 1)], + __comp) - __sd->_M_temporary[__s]; - else - // Absolute end. - __sd->_M_pieces[__iam][__s]._M_end = __sd->_M_starts[__s + 1] - - __sd->_M_starts[__s]; - } - } + else + // Absolute end. + __sd->_M_pieces[__iam][__s]._M_end = (__sd->_M_starts[__s + 1] + - __sd->_M_starts[__s]); + } + } }; -template<bool __stable, typename _RAIter, typename _Compare> - struct __possibly_stable_sort - { - }; + template<bool __stable, typename _RAIter, typename _Compare> + struct __possibly_stable_sort + { }; -template<typename _RAIter, typename _Compare> - struct __possibly_stable_sort<true, _RAIter, _Compare> - { - void operator()(const _RAIter& __begin, - const _RAIter& __end, _Compare& __comp) const + template<typename _RAIter, typename _Compare> + struct __possibly_stable_sort<true, _RAIter, _Compare> { - __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> - struct __possibly_stable_sort<false, _RAIter, _Compare> - { - void operator()(const _RAIter __begin, - const _RAIter __end, _Compare& __comp) const + template<typename _RAIter, typename _Compare> + struct __possibly_stable_sort<false, _RAIter, _Compare> { - __gnu_sequential::sort(__begin, __end, __comp); - } - }; - -template<bool __stable, typename Seq_RAIter, - typename _RAIter, typename _Compare, - typename DiffType> - struct __possibly_stable_multiway_merge - { - }; - -template<typename Seq_RAIter, typename _RAIter, - typename _Compare, typename DiffType> - struct __possibly_stable_multiway_merge - <true, Seq_RAIter, _RAIter, _Compare, - DiffType> - { - void operator()(const Seq_RAIter& __seqs_begin, - const Seq_RAIter& __seqs_end, - const _RAIter& __target, - _Compare& __comp, - DiffType __length_am) const + 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, + typename DiffType> + struct __possibly_stable_multiway_merge + { }; + + template<typename Seq_RAIter, typename _RAIter, + typename _Compare, typename _DiffType> + struct __possibly_stable_multiway_merge<true, Seq_RAIter, + _RAIter, _Compare, _DiffType> { - stable_multiway_merge(__seqs_begin, __seqs_end, __target, __length_am, - __comp, sequential_tag()); - } - }; - -template<typename Seq_RAIter, typename _RAIter, - typename _Compare, typename DiffType> - struct __possibly_stable_multiway_merge - <false, Seq_RAIter, _RAIter, _Compare, - DiffType> - { - void operator()(const Seq_RAIter& __seqs_begin, + 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, __comp, sequential_tag()); } + }; + + template<typename Seq_RAIter, typename _RAIter, + typename _Compare, typename _DiffType> + struct __possibly_stable_multiway_merge<false, Seq_RAIter, + _RAIter, _Compare, _DiffType> + { + void operator()(const Seq_RAIter& __seqs_begin, const Seq_RAIter& __seqs_end, const _RAIter& __target, _Compare& __comp, - DiffType __length_am) const + _DiffType __length_am) const + { multiway_merge(__seqs_begin, __seqs_end, __target, __length_am, + __comp, 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) { - multiway_merge(__seqs_begin, __seqs_end, __target, __length_am, __comp, - sequential_tag()); - } - }; + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + + _ThreadIndex __iam = omp_get_thread_num(); + + // Length of this thread's chunk, before merging. + _DifferenceType __length_local = + __sd->_M_starts[__iam + 1] - __sd->_M_starts[__iam]; -/** @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; - - _ThreadIndex __iam = omp_get_thread_num(); - - // Length of this thread's chunk, before merging. - _DifferenceType __length_local - = __sd->_M_starts[__iam + 1] - __sd->_M_starts[__iam]; - - // Sort in temporary storage, leave space for sentinel. - - 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>() + // Sort in temporary storage, leave space for sentinel. + + 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] + __length_local, + __sd->_M_temporary[__iam] + __length_local, __comp); - // Invariant: locally sorted subsequence in sd->_M_temporary[__iam], - // __sd->_M_temporary[__iam] + __length_local. + // Invariant: locally sorted subsequence in sd->_M_temporary[__iam], + // __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; - _SplitConsistently - <__exact, _RAIter, _Compare, _SortingPlacesIterator>() + _SplitConsistently<__exact, _RAIter, _Compare, _SortingPlacesIterator>() (__iam, __sd, __comp, __num_samples); - // Offset from __target __begin, __length after merging. - _DifferenceType __offset = 0, __length_am = 0; - for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; __s++) - { - __length_am += __sd->_M_pieces[__iam][__s]._M_end - - __sd->_M_pieces[__iam][__s]._M_begin; - __offset += __sd->_M_pieces[__iam][__s]._M_begin; - } - - typedef std::vector< - std::pair<_SortingPlacesIterator, _SortingPlacesIterator> > + // Offset from __target __begin, __length after merging. + _DifferenceType __offset = 0, __length_am = 0; + for (_ThreadIndex __s = 0; __s < __sd->_M_num_threads; __s++) + { + __length_am += (__sd->_M_pieces[__iam][__s]._M_end + - __sd->_M_pieces[__iam][__s]._M_begin); + __offset += __sd->_M_pieces[__iam][__s]._M_begin; + } + + typedef std::vector< + std::pair<_SortingPlacesIterator, _SortingPlacesIterator> > _SeqVector; - _SeqVector seqs(__sd->_M_num_threads); + _SeqVector __seqs(__sd->_M_num_threads); + + for (int __s = 0; __s < __sd->_M_num_threads; ++__s) + { + __seqs[__s] = + std::make_pair(__sd->_M_temporary[__s] + + __sd->_M_pieces[__iam][__s]._M_begin, + __sd->_M_temporary[__s] + + __sd->_M_pieces[__iam][__s]._M_end); + } + + __possibly_stable_multiway_merge< + __stable, typename _SeqVector::iterator, + _RAIter, _Compare, _DifferenceType>()(__seqs.begin(), __seqs.end(), + __sd->_M_source + __offset, __comp, + __length_am); - for (int __s = 0; __s < __sd->_M_num_threads; ++__s) - { - seqs[__s] = - std::make_pair( - __sd->_M_temporary[__s] + __sd->_M_pieces[__iam][__s]._M_begin, - __sd->_M_temporary[__s] + __sd->_M_pieces[__iam][__s]._M_end); - } +# pragma omp barrier + + ::operator delete(__sd->_M_temporary[__iam]); + } - __possibly_stable_multiway_merge< - __stable, - typename _SeqVector::iterator, - _RAIter, - _Compare, _DifferenceType>() - (seqs.begin(), seqs.end(), - __sd->_M_source + __offset, __comp, - __length_am); - -# pragma omp barrier - - ::operator delete(__sd->_M_temporary[__iam]); - } - -/** @brief PMWMS main call. - * @param __begin Begin iterator of sequence. - * @param __end End iterator of sequence. - * @param __comp Comparator. - * @param __n Length of sequence. - * @param __num_threads Number of threads to use. - */ -template<bool __stable, bool __exact, typename _RAIter, + /** @brief PMWMS main call. + * @param __begin Begin iterator of sequence. + * @param __end End iterator of sequence. + * @param __comp Comparator. + * @param __n Length of sequence. + * @param __num_threads Number of threads to use. + */ + template<bool __stable, bool __exact, typename _RAIter, typename _Compare> - void - parallel_sort_mwms(_RAIter __begin, _RAIter __end, - _Compare __comp, - _ThreadIndex __num_threads) - { - _GLIBCXX_CALL(__end - __begin) + void + parallel_sort_mwms(_RAIter __begin, _RAIter __end, + _Compare __comp, + _ThreadIndex __num_threads) + { + _GLIBCXX_CALL(__end - __begin) - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; - _DifferenceType __n = __end - __begin; + _DifferenceType __n = __end - __begin; - if (__n <= 1) - return; + if (__n <= 1) + return; - // at least one element per thread - if (__num_threads > __n) - __num_threads = static_cast<_ThreadIndex>(__n); + // at least one element per thread + if (__num_threads > __n) + __num_threads = static_cast<_ThreadIndex>(__n); - // shared variables - _PMWMSSortingData<_RAIter> __sd; - _DifferenceType* _M_starts; + // shared variables + _PMWMSSortingData<_RAIter> __sd; + _DifferenceType* __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 # pragma omp single - { - __sd._M_num_threads = __num_threads; - __sd._M_source = __begin; - - __sd._M_temporary = new _ValueType*[__num_threads]; - - if (!__exact) - { - _DifferenceType __size = - (_Settings::get().sort_mwms_oversampling * __num_threads - 1) - * __num_threads; - __sd._M_samples = static_cast<_ValueType*>( - ::operator new(__size * sizeof(_ValueType))); - } - else - __sd._M_samples = NULL; - - __sd._M_offsets = new _DifferenceType[__num_threads - 1]; - __sd._M_pieces - = new std::vector<_Piece<_DifferenceType> >[__num_threads]; - for (int __s = 0; __s < __num_threads; ++__s) - __sd._M_pieces[__s].resize(__num_threads); - _M_starts = __sd._M_starts - = new _DifferenceType[__num_threads + 1]; - - _DifferenceType __chunk_length = __n / __num_threads; - _DifferenceType __split = __n % __num_threads; - _DifferenceType __pos = 0; - for (int __i = 0; __i < __num_threads; ++__i) - { - _M_starts[__i] = __pos; - __pos += (__i < __split) - ? (__chunk_length + 1) : __chunk_length; - } - _M_starts[__num_threads] = __pos; - } //single + { + __sd._M_num_threads = __num_threads; + __sd._M_source = __begin; + + __sd._M_temporary = new _ValueType*[__num_threads]; + + if (!__exact) + { + _DifferenceType __size = + (_Settings::get().sort_mwms_oversampling * __num_threads - 1) + * __num_threads; + __sd._M_samples = static_cast<_ValueType*> + (::operator new(__size * sizeof(_ValueType))); + } + else + __sd._M_samples = NULL; + + __sd._M_offsets = new _DifferenceType[__num_threads - 1]; + __sd._M_pieces + = new std::vector<_Piece<_DifferenceType> >[__num_threads]; + for (int __s = 0; __s < __num_threads; ++__s) + __sd._M_pieces[__s].resize(__num_threads); + __starts = __sd._M_starts = new _DifferenceType[__num_threads + 1]; + + _DifferenceType __chunk_length = __n / __num_threads; + _DifferenceType __split = __n % __num_threads; + _DifferenceType __pos = 0; + for (int __i = 0; __i < __num_threads; ++__i) + { + __starts[__i] = __pos; + __pos += ((__i < __split) + ? (__chunk_length + 1) : __chunk_length); + } + __starts[__num_threads] = __pos; + } //single // Now sort in parallel. parallel_sort_mwms_pu<__stable, __exact>(&__sd, __comp); } //parallel - delete[] _M_starts; - delete[] __sd._M_temporary; + delete[] __starts; + delete[] __sd._M_temporary; - if (!__exact) - ::operator delete(__sd._M_samples); + if (!__exact) + ::operator delete(__sd._M_samples); + + delete[] __sd._M_offsets; + delete[] __sd._M_pieces; + } - delete[] __sd._M_offsets; - delete[] __sd._M_pieces; - } } //namespace __gnu_parallel #endif /* _GLIBCXX_PARALLEL_MULTIWAY_MERGESORT_H */ diff --git a/libstdc++-v3/include/parallel/numeric b/libstdc++-v3/include/parallel/numeric index 06985ba99c9..6c5607cedc5 100644 --- a/libstdc++-v3/include/parallel/numeric +++ b/libstdc++-v3/include/parallel/numeric @@ -69,7 +69,7 @@ namespace __parallel __accumulate_switch(_IIter __begin, _IIter __end, _Tp __init, _IteratorTag) { return accumulate(__begin, __end, __init, -__gnu_parallel::sequential_tag()); } + __gnu_parallel::sequential_tag()); } template<typename _IIter, typename _Tp, typename _BinaryOperation, typename _IteratorTag> @@ -435,7 +435,7 @@ __gnu_parallel::sequential_tag()); } __for_each_template_random_access_ed( __begin_pair, __end_pair, __bin_op, __functionality, __gnu_parallel::_DummyReduct(), __dummy, __dummy, -1); - return __functionality.finish_iterator; + return __functionality._M_finish_iterator; } else return adjacent_difference(__begin, __end, __result, __bin_op, diff --git a/libstdc++-v3/include/parallel/omp_loop.h b/libstdc++-v3/include/parallel/omp_loop.h index 2424bfbdde8..d07fd7a9307 100644 --- a/libstdc++-v3/include/parallel/omp_loop.h +++ b/libstdc++-v3/include/parallel/omp_loop.h @@ -41,74 +41,74 @@ namespace __gnu_parallel { -/** @brief Embarrassingly parallel algorithm for random access - * iterators, using an OpenMP for loop. - * - * @param __begin Begin iterator of element sequence. - * @param __end End iterator of element sequence. - * @param __o User-supplied functor (comparator, predicate, adding - * functor, etc.). - * @param __f Functor to "process" an element with __op (depends on - * desired functionality, e. g. for std::for_each(), ...). - * @param __r Functor to "add" a single __result to the already - * processed elements (depends on functionality). - * @param __base Base value for reduction. - * @param __output Pointer to position where final result is written to - * @param __bound Maximum number of elements processed (e. g. for - * std::count_n()). - * @return User-supplied functor (that may contain a part of the result). - */ -template<typename _RAIter, - typename _Op, - typename _Fu, - typename _Red, - typename _Result> - _Op - __for_each_template_random_access_omp_loop( - _RAIter __begin, _RAIter __end, _Op __o, _Fu& __f, _Red __r, - _Result __base, _Result& __output, - typename std::iterator_traits<_RAIter>::difference_type __bound) - { - typedef typename - std::iterator_traits<_RAIter>::difference_type + /** @brief Embarrassingly parallel algorithm for random access + * iterators, using an OpenMP for loop. + * + * @param __begin Begin iterator of element sequence. + * @param __end End iterator of element sequence. + * @param __o User-supplied functor (comparator, predicate, adding + * functor, etc.). + * @param __f Functor to "process" an element with __op (depends on + * desired functionality, e. g. for std::for_each(), ...). + * @param __r Functor to "add" a single __result to the already + * processed elements (depends on functionality). + * @param __base Base value for reduction. + * @param __output Pointer to position where final result is written to + * @param __bound Maximum number of elements processed (e. g. for + * std::count_n()). + * @return User-supplied functor (that may contain a part of the result). + */ + template<typename _RAIter, + typename _Op, + typename _Fu, + typename _Red, + typename _Result> + _Op + __for_each_template_random_access_omp_loop(_RAIter __begin, _RAIter __end, + _Op __o, _Fu& __f, _Red __r, + _Result __base, + _Result& __output, + typename std::iterator_traits<_RAIter>::difference_type __bound) + { + typedef typename std::iterator_traits<_RAIter>::difference_type _DifferenceType; - _DifferenceType __length = __end - __begin; - _ThreadIndex __num_threads = - __gnu_parallel::min<_DifferenceType>(__get_max_threads(), __length); + _DifferenceType __length = __end - __begin; + _ThreadIndex __num_threads = __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 - { - __num_threads = omp_get_num_threads(); - __thread_results = new _Result[__num_threads]; + { + __num_threads = omp_get_num_threads(); + __thread_results = new _Result[__num_threads]; - for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) - __thread_results[__i] = _Result(); - } + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + __thread_results[__i] = _Result(); + } _ThreadIndex __iam = omp_get_thread_num(); #pragma omp for schedule(dynamic, _Settings::get().workstealing_chunk_size) for (_DifferenceType __pos = 0; __pos < __length; ++__pos) - __thread_results[__iam] = - __r(__thread_results[__iam], __f(__o, __begin+__pos)); + __thread_results[__iam] = __r(__thread_results[__iam], + __f(__o, __begin+__pos)); } //parallel - for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) __output = __r(__output, __thread_results[__i]); - delete [] __thread_results; + delete [] __thread_results; - // Points to last element processed (needed as return value for - // some algorithms like transform). - __f._M_finish_iterator = __begin + __length; + // Points to last element processed (needed as return value for + // some algorithms like transform). + __f._M_finish_iterator = __begin + __length; - return __o; - } + return __o; + } } // end namespace diff --git a/libstdc++-v3/include/parallel/omp_loop_static.h b/libstdc++-v3/include/parallel/omp_loop_static.h index 3d9ed841ac6..f43726e1973 100644 --- a/libstdc++-v3/include/parallel/omp_loop_static.h +++ b/libstdc++-v3/include/parallel/omp_loop_static.h @@ -40,7 +40,6 @@ namespace __gnu_parallel { - /** @brief Embarrassingly parallel algorithm for random access * iterators, using an OpenMP for loop with static scheduling. * @@ -58,37 +57,38 @@ namespace __gnu_parallel * std::count_n()). * @return User-supplied functor (that may contain a part of the result). */ -template<typename _RAIter, - typename _Op, - typename _Fu, - typename _Red, - typename _Result> - _Op - __for_each_template_random_access_omp_loop_static( - _RAIter __begin, _RAIter __end, _Op __o, _Fu& __f, _Red __r, - _Result __base, _Result& __output, - typename std::iterator_traits<_RAIter>::difference_type __bound) - { - typedef typename - std::iterator_traits<_RAIter>::difference_type - _DifferenceType; - - _DifferenceType __length = __end - __begin; - _ThreadIndex __num_threads = - std::min<_DifferenceType>(__get_max_threads(), __length); - - _Result *__thread_results; - -# pragma omp parallel num_threads(__num_threads) + template<typename _RAIter, + typename _Op, + typename _Fu, + typename _Red, + typename _Result> + _Op + __for_each_template_random_access_omp_loop_static(_RAIter __begin, + _RAIter __end, _Op __o, + _Fu& __f, _Red __r, + _Result __base, + _Result& __output, + typename std::iterator_traits<_RAIter>::difference_type __bound) + { + typedef typename std::iterator_traits<_RAIter>::difference_type + _DifferenceType; + + _DifferenceType __length = __end - __begin; + _ThreadIndex __num_threads = std::min<_DifferenceType> + (__get_max_threads(), __length); + + _Result *__thread_results; + +# pragma omp parallel num_threads(__num_threads) { # pragma omp single - { - __num_threads = omp_get_num_threads(); - __thread_results = new _Result[__num_threads]; + { + __num_threads = omp_get_num_threads(); + __thread_results = new _Result[__num_threads]; - for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) - __thread_results[__i] = _Result(); - } + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + __thread_results[__i] = _Result(); + } _ThreadIndex __iam = omp_get_thread_num(); @@ -98,17 +98,17 @@ template<typename _RAIter, __f(__o, __begin+__pos)); } //parallel - for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) - __output = __r(__output, __thread_results[__i]); + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + __output = __r(__output, __thread_results[__i]); - delete [] __thread_results; + delete [] __thread_results; - // Points to last element processed (needed as return value for - // some algorithms like transform). - __f.finish_iterator = __begin + __length; + // Points to last element processed (needed as return value for + // some algorithms like transform). + __f.finish_iterator = __begin + __length; - return __o; - } + return __o; + } } // end namespace diff --git a/libstdc++-v3/include/parallel/par_loop.h b/libstdc++-v3/include/parallel/par_loop.h index c842364a6fd..1e21d3ad042 100644 --- a/libstdc++-v3/include/parallel/par_loop.h +++ b/libstdc++-v3/include/parallel/par_loop.h @@ -40,94 +40,92 @@ namespace __gnu_parallel { - -/** @brief Embarrassingly parallel algorithm for random access - * iterators, using hand-crafted parallelization by equal splitting - * the work. - * - * @param __begin Begin iterator of element sequence. - * @param __end End iterator of element sequence. - * @param __o User-supplied functor (comparator, predicate, adding - * functor, ...) - * @param __f Functor to "process" an element with __op (depends on - * desired functionality, e. g. for std::for_each(), ...). - * @param __r Functor to "add" a single __result to the already - * processed elements (depends on functionality). - * @param __base Base value for reduction. - * @param __output Pointer to position where final result is written to - * @param __bound Maximum number of elements processed (e. g. for - * std::count_n()). - * @return User-supplied functor (that may contain a part of the result). - */ -template<typename _RAIter, - typename _Op, - typename _Fu, - typename _Red, - typename _Result> - _Op - __for_each_template_random_access_ed( - _RAIter __begin, _RAIter __end, _Op __o, _Fu& __f, _Red __r, - _Result __base, _Result& __output, - typename std::iterator_traits<_RAIter>::difference_type __bound) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; - const _DifferenceType __length = __end - __begin; - _Result *__thread_results; - bool* __constructed; - - _ThreadIndex __num_threads = - __gnu_parallel::min<_DifferenceType>(__get_max_threads(), __length); - -# pragma omp parallel num_threads(__num_threads) + /** @brief Embarrassingly parallel algorithm for random access + * iterators, using hand-crafted parallelization by equal splitting + * the work. + * + * @param __begin Begin iterator of element sequence. + * @param __end End iterator of element sequence. + * @param __o User-supplied functor (comparator, predicate, adding + * functor, ...) + * @param __f Functor to "process" an element with __op (depends on + * desired functionality, e. g. for std::for_each(), ...). + * @param __r Functor to "add" a single __result to the already + * processed elements (depends on functionality). + * @param __base Base value for reduction. + * @param __output Pointer to position where final result is written to + * @param __bound Maximum number of elements processed (e. g. for + * std::count_n()). + * @return User-supplied functor (that may contain a part of the result). + */ + template<typename _RAIter, + typename _Op, + typename _Fu, + typename _Red, + typename _Result> + _Op + __for_each_template_random_access_ed(_RAIter __begin, _RAIter __end, + _Op __o, _Fu& __f, _Red __r, + _Result __base, _Result& __output, + typename std::iterator_traits<_RAIter>::difference_type __bound) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + const _DifferenceType __length = __end - __begin; + _Result *__thread_results; + bool* __constructed; + + _ThreadIndex __num_threads = __gnu_parallel::min<_DifferenceType> + (__get_max_threads(), __length); + +# pragma omp parallel num_threads(__num_threads) { # pragma omp single - { - __num_threads = omp_get_num_threads(); - __thread_results = - static_cast<_Result*>( - ::operator new(__num_threads * sizeof(_Result))); - __constructed = new bool[__num_threads]; - } - - _ThreadIndex __iam = omp_get_thread_num(); - - // Neutral element. - _Result* __reduct = - static_cast<_Result*>(::operator new(sizeof(_Result))); - - _DifferenceType - __start = equally_split_point(__length, __num_threads, __iam), - __stop = equally_split_point(__length, __num_threads, __iam + 1); - - if (__start < __stop) - { - new(__reduct) _Result(__f(__o, __begin + __start)); - ++__start; - __constructed[__iam] = true; - } - else - __constructed[__iam] = false; - - for (; __start < __stop; ++__start) - *__reduct = __r(*__reduct, __f(__o, __begin + __start)); - - __thread_results[__iam] = *__reduct; + { + __num_threads = omp_get_num_threads(); + __thread_results = static_cast<_Result*> + (::operator new(__num_threads * sizeof(_Result))); + __constructed = new bool[__num_threads]; + } + + _ThreadIndex __iam = omp_get_thread_num(); + + // Neutral element. + _Result* __reduct = static_cast<_Result*> + (::operator new(sizeof(_Result))); + + _DifferenceType + __start = equally_split_point(__length, __num_threads, __iam), + __stop = equally_split_point(__length, __num_threads, __iam + 1); + + if (__start < __stop) + { + new(__reduct) _Result(__f(__o, __begin + __start)); + ++__start; + __constructed[__iam] = true; + } + else + __constructed[__iam] = false; + + for (; __start < __stop; ++__start) + *__reduct = __r(*__reduct, __f(__o, __begin + __start)); + + __thread_results[__iam] = *__reduct; } //parallel - for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) - if (__constructed[__i]) - __output = __r(__output, __thread_results[__i]); + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + if (__constructed[__i]) + __output = __r(__output, __thread_results[__i]); - // Points to last element processed (needed as return value for - // some algorithms like transform). - __f._M_finish_iterator = __begin + __length; + // Points to last element processed (needed as return value for + // some algorithms like transform). + __f._M_finish_iterator = __begin + __length; - delete[] __thread_results; - delete[] __constructed; + delete[] __thread_results; + delete[] __constructed; - return __o; - } + return __o; + } } // end namespace diff --git a/libstdc++-v3/include/parallel/partial_sum.h b/libstdc++-v3/include/parallel/partial_sum.h index b121e1ff8c7..02404203f4e 100644 --- a/libstdc++-v3/include/parallel/partial_sum.h +++ b/libstdc++-v3/include/parallel/partial_sum.h @@ -43,114 +43,116 @@ namespace __gnu_parallel { // Problem: there is no 0-element given. -/** @brief Base case prefix sum routine. - * @param __begin Begin iterator of input sequence. - * @param __end End iterator of input sequence. - * @param __result Begin iterator of output sequence. - * @param __bin_op Associative binary function. - * @param __value Start value. Must be passed since the neutral - * element is unknown in general. - * @return End iterator of output sequence. */ -template<typename _IIter, - typename _OutputIterator, - typename _BinaryOperation> - _OutputIterator - __parallel_partial_sum_basecase( - _IIter __begin, _IIter __end, _OutputIterator __result, - _BinaryOperation __bin_op, - typename std::iterator_traits <_IIter>::value_type __value) - { - if (__begin == __end) + /** @brief Base case prefix sum routine. + * @param __begin Begin iterator of input sequence. + * @param __end End iterator of input sequence. + * @param __result Begin iterator of output sequence. + * @param __bin_op Associative binary function. + * @param __value Start value. Must be passed since the neutral + * element is unknown in general. + * @return End iterator of output sequence. */ + template<typename _IIter, + typename _OutputIterator, + typename _BinaryOperation> + _OutputIterator + __parallel_partial_sum_basecase(_IIter __begin, _IIter __end, + _OutputIterator __result, + _BinaryOperation __bin_op, + typename std::iterator_traits <_IIter>::value_type __value) + { + if (__begin == __end) + return __result; + + while (__begin != __end) + { + __value = __bin_op(__value, *__begin); + *__result = __value; + ++__result; + ++__begin; + } return __result; - - while (__begin != __end) - { - __value = __bin_op(__value, *__begin); - *__result = __value; - ++__result; - ++__begin; - } - return __result; - } - -/** @brief Parallel partial sum implementation, two-phase approach, - no recursion. - * @param __begin Begin iterator of input sequence. - * @param __end End iterator of input sequence. - * @param __result Begin iterator of output sequence. - * @param __bin_op Associative binary function. - * @param __n Length of sequence. - * @param __num_threads Number of threads to use. - * @return End iterator of output sequence. - */ -template<typename _IIter, - typename _OutputIterator, - typename _BinaryOperation> - _OutputIterator - __parallel_partial_sum_linear( - _IIter __begin, _IIter __end, _OutputIterator __result, - _BinaryOperation __bin_op, - typename std::iterator_traits<_IIter>::difference_type __n) - { - 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 = + } + + /** @brief Parallel partial sum implementation, two-phase approach, + no recursion. + * @param __begin Begin iterator of input sequence. + * @param __end End iterator of input sequence. + * @param __result Begin iterator of output sequence. + * @param __bin_op Associative binary function. + * @param __n Length of sequence. + * @param __num_threads Number of threads to use. + * @return End iterator of output sequence. + */ + template<typename _IIter, + typename _OutputIterator, + typename _BinaryOperation> + _OutputIterator + __parallel_partial_sum_linear(_IIter __begin, _IIter __end, + _OutputIterator __result, + _BinaryOperation __bin_op, + typename std::iterator_traits<_IIter>::difference_type __n) + { + 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); - if (__num_threads < 2) - { - *__result = *__begin; - return __parallel_partial_sum_basecase( - __begin + 1, __end, __result + 1, __bin_op, *__begin); - } + if (__num_threads < 2) + { + *__result = *__begin; + return __parallel_partial_sum_basecase(__begin + 1, __end, + __result + 1, __bin_op, + *__begin); + } - _DifferenceType* __borders; - _ValueType* __sums; + _DifferenceType* __borders; + _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 - { - __num_threads = omp_get_num_threads(); - - __borders = new _DifferenceType[__num_threads + 2]; - - if (__s.partial_sum_dilation == 1.0f) - equally_split(__n, __num_threads + 1, __borders); - else - { - _DifferenceType __chunk_length = - ((double)__n - / ((double)__num_threads + __s.partial_sum_dilation)), - __borderstart = __n - __num_threads * __chunk_length; - __borders[0] = 0; - for (int __i = 1; __i < (__num_threads + 1); ++__i) - { - __borders[__i] = __borderstart; - __borderstart += __chunk_length; - } - __borders[__num_threads + 1] = __n; - } - - __sums = static_cast<_ValueType*>(::operator new(sizeof(_ValueType) + { + __num_threads = omp_get_num_threads(); + + __borders = new _DifferenceType[__num_threads + 2]; + + if (__s.partial_sum_dilation == 1.0f) + equally_split(__n, __num_threads + 1, __borders); + else + { + _DifferenceType __chunk_length = + ((double)__n + / ((double)__num_threads + __s.partial_sum_dilation)), + __borderstart = __n - __num_threads * __chunk_length; + __borders[0] = 0; + for (int __i = 1; __i < (__num_threads + 1); ++__i) + { + __borders[__i] = __borderstart; + __borderstart += __chunk_length; + } + __borders[__num_threads + 1] = __n; + } + + __sums = static_cast<_ValueType*>(::operator new(sizeof(_ValueType) * __num_threads)); - _OutputIterator __target_end; - } //single + _OutputIterator __target_end; + } //single _ThreadIndex __iam = omp_get_thread_num(); if (__iam == 0) { *__result = *__begin; - __parallel_partial_sum_basecase( - __begin + 1, __begin + __borders[1], __result + 1, - __bin_op, *__begin); + __parallel_partial_sum_basecase(__begin + 1, + __begin + __borders[1], + __result + 1, + __bin_op, *__begin); ::new(&(__sums[__iam])) _ValueType(*(__result + __borders[1] - 1)); } else @@ -166,58 +168,57 @@ template<typename _IIter, # pragma omp barrier # pragma omp single - __parallel_partial_sum_basecase(__sums + 1, __sums + __num_threads, - __sums + 1, __bin_op, __sums[0]); + __parallel_partial_sum_basecase(__sums + 1, __sums + __num_threads, + __sums + 1, __bin_op, __sums[0]); # pragma omp barrier - // Still same team. - __parallel_partial_sum_basecase( - __begin + __borders[__iam + 1], - __begin + __borders[__iam + 2], - __result + __borders[__iam + 1], - __bin_op, __sums[__iam]); + // Still same team. + __parallel_partial_sum_basecase(__begin + __borders[__iam + 1], + __begin + __borders[__iam + 2], + __result + __borders[__iam + 1], + __bin_op, __sums[__iam]); } //parallel - ::operator delete(__sums); - delete[] __borders; - - return __result + __n; - } - -/** @brief Parallel partial sum front-__end. - * @param __begin Begin iterator of input sequence. - * @param __end End iterator of input sequence. - * @param __result Begin iterator of output sequence. - * @param __bin_op Associative binary function. - * @return End iterator of output sequence. */ -template<typename _IIter, - typename _OutputIterator, - typename _BinaryOperation> - _OutputIterator - __parallel_partial_sum(_IIter __begin, _IIter __end, - _OutputIterator __result, _BinaryOperation __bin_op) - { - _GLIBCXX_CALL(__begin - __end) - - typedef std::iterator_traits<_IIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _DifferenceType __n = __end - __begin; - - switch (_Settings::get().partial_sum_algorithm) - { - case LINEAR: - // Need an initial offset. - return __parallel_partial_sum_linear( - __begin, __end, __result, __bin_op, __n); - default: - // Partial_sum algorithm not implemented. - _GLIBCXX_PARALLEL_ASSERT(0); - return __result + __n; - } - } + ::operator delete(__sums); + delete[] __borders; + + return __result + __n; + } + + /** @brief Parallel partial sum front-__end. + * @param __begin Begin iterator of input sequence. + * @param __end End iterator of input sequence. + * @param __result Begin iterator of output sequence. + * @param __bin_op Associative binary function. + * @return End iterator of output sequence. */ + template<typename _IIter, + typename _OutputIterator, + typename _BinaryOperation> + _OutputIterator + __parallel_partial_sum(_IIter __begin, _IIter __end, + _OutputIterator __result, _BinaryOperation __bin_op) + { + _GLIBCXX_CALL(__begin - __end) + + typedef std::iterator_traits<_IIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + + _DifferenceType __n = __end - __begin; + + switch (_Settings::get().partial_sum_algorithm) + { + case LINEAR: + // Need an initial offset. + return __parallel_partial_sum_linear(__begin, __end, __result, + __bin_op, __n); + default: + // Partial_sum algorithm not implemented. + _GLIBCXX_PARALLEL_ASSERT(0); + return __result + __n; + } + } } #endif /* _GLIBCXX_PARALLEL_PARTIAL_SUM_H */ diff --git a/libstdc++-v3/include/parallel/partition.h b/libstdc++-v3/include/parallel/partition.h index 11362939fc8..86723c51270 100644 --- a/libstdc++-v3/include/parallel/partition.h +++ b/libstdc++-v3/include/parallel/partition.h @@ -44,387 +44,391 @@ namespace __gnu_parallel { -/** @brief Parallel implementation of std::partition. - * @param __begin Begin iterator of input sequence to split. - * @param __end End iterator of input sequence to split. - * @param __pred Partition predicate, possibly including some kind of pivot. - * @param __num_threads Maximum number of threads to use for this task. - * @return Number of elements not fulfilling the predicate. */ -template<typename _RAIter, typename _Predicate> - typename std::iterator_traits<_RAIter>::difference_type - __parallel_partition(_RAIter __begin, _RAIter __end, - _Predicate __pred, _ThreadIndex __num_threads) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _DifferenceType __n = __end - __begin; - - _GLIBCXX_CALL(__n) - - const _Settings& __s = _Settings::get(); - - // Shared. - _GLIBCXX_VOLATILE _DifferenceType __left = 0, __right = __n - 1; - _GLIBCXX_VOLATILE _DifferenceType __leftover_left, __leftover_right; - _GLIBCXX_VOLATILE _DifferenceType __leftnew, __rightnew; - - bool* __reserved_left = NULL, * __reserved_right = NULL; - - _DifferenceType __chunk_size; - - omp_lock_t __result_lock; - omp_init_lock(&__result_lock); - - //at least two chunks per thread - if(__right - __left + 1 >= 2 * __num_threads * __chunk_size) -# pragma omp parallel num_threads(__num_threads) - { -# pragma omp single - { - __num_threads = omp_get_num_threads(); - __reserved_left = new bool[__num_threads]; - __reserved_right = new bool[__num_threads]; - - if (__s.partition_chunk_share > 0.0) - __chunk_size = std::max<_DifferenceType>( - __s.partition_chunk_size, - (double)__n * __s.partition_chunk_share / - (double)__num_threads); - else - __chunk_size = __s.partition_chunk_size; - } - - while (__right - __left + 1 >= 2 * __num_threads * __chunk_size) - { -# pragma omp single - { - _DifferenceType __num_chunks - = (__right - __left + 1) / __chunk_size; - - for (int __r = 0; __r < __num_threads; ++__r) - { - __reserved_left[__r] = false; - __reserved_right[__r] = false; - } - __leftover_left = 0; - __leftover_right = 0; - } //implicit barrier - - // Private. - _DifferenceType __thread_left, __thread_left_border, - __thread_right, __thread_right_border; - __thread_left = __left + 1; - - // Just to satisfy the condition below. - __thread_left_border = __thread_left - 1; - __thread_right = __n - 1; - __thread_right_border = __thread_right + 1; - - bool __iam_finished = false; - while (!__iam_finished) - { - if (__thread_left > __thread_left_border) - { - omp_set_lock(&__result_lock); - if (__left + (__chunk_size - 1) > __right) - __iam_finished = true; - else - { - __thread_left = __left; - __thread_left_border = __left + (__chunk_size - 1); - __left += __chunk_size; - } - omp_unset_lock(&__result_lock); - } - - if (__thread_right < __thread_right_border) - { - omp_set_lock(&__result_lock); - if (__left > __right - (__chunk_size - 1)) - __iam_finished = true; - else - { - __thread_right = __right; - __thread_right_border = __right - (__chunk_size - 1); - __right -= __chunk_size; - } - omp_unset_lock(&__result_lock); - } - - if (__iam_finished) - break; - - // Swap as usual. - while (__thread_left < __thread_right) - { - while (__pred(__begin[__thread_left]) - && __thread_left <= __thread_left_border) - ++__thread_left; - while (!__pred(__begin[__thread_right]) - && __thread_right >= __thread_right_border) - --__thread_right; - - if (__thread_left > __thread_left_border - || __thread_right < __thread_right_border) - // Fetch new chunk(__s). - break; - - std::swap(__begin[__thread_left], __begin[__thread_right]); - ++__thread_left; - --__thread_right; - } - } - - // Now swap the leftover chunks to the right places. - if (__thread_left <= __thread_left_border) -# pragma omp atomic - ++__leftover_left; - if (__thread_right >= __thread_right_border) -# pragma omp atomic - ++__leftover_right; - -# pragma omp barrier - -# pragma omp single - { - __leftnew = __left - __leftover_left * __chunk_size; - __rightnew = __right + __leftover_right * __chunk_size; - } - -# pragma omp barrier - - // <=> __thread_left_border + (__chunk_size - 1) >= __leftnew - if (__thread_left <= __thread_left_border - && __thread_left_border >= __leftnew) - { - // Chunk already in place, reserve spot. - __reserved_left - [(__left - (__thread_left_border + 1)) / __chunk_size] - = true; - } - - // <=> __thread_right_border - (__chunk_size - 1) <= __rightnew - if (__thread_right >= __thread_right_border - && __thread_right_border <= __rightnew) - { - // Chunk already in place, reserve spot. - __reserved_right[((__thread_right_border - 1) - __right) - / __chunk_size] = true; - } - -# pragma omp barrier - - if (__thread_left <= __thread_left_border - && __thread_left_border < __leftnew) - { - // Find spot and swap. - _DifferenceType __swapstart = -1; - omp_set_lock(&__result_lock); - for (int __r = 0; __r < __leftover_left; ++__r) - if (!__reserved_left[__r]) - { - __reserved_left[__r] = true; - __swapstart = __left - (__r + 1) * __chunk_size; - break; - } - omp_unset_lock(&__result_lock); + /** @brief Parallel implementation of std::partition. + * @param __begin Begin iterator of input sequence to split. + * @param __end End iterator of input sequence to split. + * @param __pred Partition predicate, possibly including some kind + * of pivot. + * @param __num_threads Maximum number of threads to use for this task. + * @return Number of elements not fulfilling the predicate. */ + template<typename _RAIter, typename _Predicate> + typename std::iterator_traits<_RAIter>::difference_type + __parallel_partition(_RAIter __begin, _RAIter __end, + _Predicate __pred, _ThreadIndex __num_threads) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + + _DifferenceType __n = __end - __begin; + + _GLIBCXX_CALL(__n) + + const _Settings& __s = _Settings::get(); + + // Shared. + _GLIBCXX_VOLATILE _DifferenceType __left = 0, __right = __n - 1; + _GLIBCXX_VOLATILE _DifferenceType __leftover_left, __leftover_right; + _GLIBCXX_VOLATILE _DifferenceType __leftnew, __rightnew; + + bool* __reserved_left = NULL, * __reserved_right = NULL; + + _DifferenceType __chunk_size; + + omp_lock_t __result_lock; + omp_init_lock(&__result_lock); + + //at least two chunks per thread + if (__right - __left + 1 >= 2 * __num_threads * __chunk_size) +# pragma omp parallel num_threads(__num_threads) + { +# pragma omp single + { + __num_threads = omp_get_num_threads(); + __reserved_left = new bool[__num_threads]; + __reserved_right = new bool[__num_threads]; + + if (__s.partition_chunk_share > 0.0) + __chunk_size = std::max<_DifferenceType> + (__s.partition_chunk_size, (double)__n + * __s.partition_chunk_share / (double)__num_threads); + else + __chunk_size = __s.partition_chunk_size; + } + + while (__right - __left + 1 >= 2 * __num_threads * __chunk_size) + { +# pragma omp single + { + _DifferenceType __num_chunks = ((__right - __left + 1) + / __chunk_size); + + for (int __r = 0; __r < __num_threads; ++__r) + { + __reserved_left[__r] = false; + __reserved_right[__r] = false; + } + __leftover_left = 0; + __leftover_right = 0; + } //implicit barrier + + // Private. + _DifferenceType __thread_left, __thread_left_border, + __thread_right, __thread_right_border; + __thread_left = __left + 1; + + // Just to satisfy the condition below. + __thread_left_border = __thread_left - 1; + __thread_right = __n - 1; + __thread_right_border = __thread_right + 1; + + bool __iam_finished = false; + while (!__iam_finished) + { + if (__thread_left > __thread_left_border) + { + omp_set_lock(&__result_lock); + if (__left + (__chunk_size - 1) > __right) + __iam_finished = true; + else + { + __thread_left = __left; + __thread_left_border = __left + (__chunk_size - 1); + __left += __chunk_size; + } + omp_unset_lock(&__result_lock); + } + + if (__thread_right < __thread_right_border) + { + omp_set_lock(&__result_lock); + if (__left > __right - (__chunk_size - 1)) + __iam_finished = true; + else + { + __thread_right = __right; + __thread_right_border = __right - (__chunk_size - 1); + __right -= __chunk_size; + } + omp_unset_lock(&__result_lock); + } + + if (__iam_finished) + break; + + // Swap as usual. + while (__thread_left < __thread_right) + { + while (__pred(__begin[__thread_left]) + && __thread_left <= __thread_left_border) + ++__thread_left; + while (!__pred(__begin[__thread_right]) + && __thread_right >= __thread_right_border) + --__thread_right; + + if (__thread_left > __thread_left_border + || __thread_right < __thread_right_border) + // Fetch new chunk(__s). + break; + + std::swap(__begin[__thread_left], + __begin[__thread_right]); + ++__thread_left; + --__thread_right; + } + } + + // Now swap the leftover chunks to the right places. + if (__thread_left <= __thread_left_border) +# pragma omp atomic + ++__leftover_left; + if (__thread_right >= __thread_right_border) +# pragma omp atomic + ++__leftover_right; + +# pragma omp barrier + +# pragma omp single + { + __leftnew = __left - __leftover_left * __chunk_size; + __rightnew = __right + __leftover_right * __chunk_size; + } + +# pragma omp barrier + + // <=> __thread_left_border + (__chunk_size - 1) >= __leftnew + if (__thread_left <= __thread_left_border + && __thread_left_border >= __leftnew) + { + // Chunk already in place, reserve spot. + __reserved_left[(__left - (__thread_left_border + 1)) + / __chunk_size] = true; + } + + // <=> __thread_right_border - (__chunk_size - 1) <= __rightnew + if (__thread_right >= __thread_right_border + && __thread_right_border <= __rightnew) + { + // Chunk already in place, reserve spot. + __reserved_right[((__thread_right_border - 1) - __right) + / __chunk_size] = true; + } + +# pragma omp barrier + + if (__thread_left <= __thread_left_border + && __thread_left_border < __leftnew) + { + // Find spot and swap. + _DifferenceType __swapstart = -1; + omp_set_lock(&__result_lock); + for (int __r = 0; __r < __leftover_left; ++__r) + if (!__reserved_left[__r]) + { + __reserved_left[__r] = true; + __swapstart = __left - (__r + 1) * __chunk_size; + break; + } + omp_unset_lock(&__result_lock); #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(__swapstart != -1); + _GLIBCXX_PARALLEL_ASSERT(__swapstart != -1); #endif - std::swap_ranges(__begin + __thread_left_border - - (__chunk_size - 1), - __begin + __thread_left_border + 1, - __begin + __swapstart); - } - - if (__thread_right >= __thread_right_border - && __thread_right_border > __rightnew) - { - // Find spot and swap - _DifferenceType __swapstart = -1; - omp_set_lock(&__result_lock); - for (int __r = 0; __r < __leftover_right; ++__r) - if (!__reserved_right[__r]) - { - __reserved_right[__r] = true; - __swapstart = __right + __r * __chunk_size + 1; - break; - } - omp_unset_lock(&__result_lock); + std::swap_ranges(__begin + __thread_left_border + - (__chunk_size - 1), + __begin + __thread_left_border + 1, + __begin + __swapstart); + } + + if (__thread_right >= __thread_right_border + && __thread_right_border > __rightnew) + { + // Find spot and swap + _DifferenceType __swapstart = -1; + omp_set_lock(&__result_lock); + for (int __r = 0; __r < __leftover_right; ++__r) + if (!__reserved_right[__r]) + { + __reserved_right[__r] = true; + __swapstart = __right + __r * __chunk_size + 1; + break; + } + omp_unset_lock(&__result_lock); #if _GLIBCXX_ASSERTIONS - _GLIBCXX_PARALLEL_ASSERT(__swapstart != -1); + _GLIBCXX_PARALLEL_ASSERT(__swapstart != -1); #endif - std::swap_ranges( - __begin + __thread_right_border, - __begin + __thread_right_border + __chunk_size, - __begin + __swapstart); - } + std::swap_ranges(__begin + __thread_right_border, + __begin + __thread_right_border + + __chunk_size, __begin + __swapstart); + } #if _GLIBCXX_ASSERTIONS # pragma omp barrier # pragma omp single - { - for (int __r = 0; __r < __leftover_left; ++__r) - _GLIBCXX_PARALLEL_ASSERT(__reserved_left[__r]); - for (int __r = 0; __r < __leftover_right; ++__r) - _GLIBCXX_PARALLEL_ASSERT(__reserved_right[__r]); - } + { + for (int __r = 0; __r < __leftover_left; ++__r) + _GLIBCXX_PARALLEL_ASSERT(__reserved_left[__r]); + for (int __r = 0; __r < __leftover_right; ++__r) + _GLIBCXX_PARALLEL_ASSERT(__reserved_right[__r]); + } # pragma omp barrier #endif # pragma omp barrier - __left = __leftnew; - __right = __rightnew; - } -# pragma omp flush(__left, __right) - } // end "recursion" //parallel - - _DifferenceType __final_left = __left, __final_right = __right; - - while (__final_left < __final_right) - { - // Go right until key is geq than pivot. - while (__pred(__begin[__final_left]) && __final_left < __final_right) - ++__final_left; - - // Go left until key is less than pivot. - while (!__pred(__begin[__final_right]) && __final_left < __final_right) - --__final_right; - - if (__final_left == __final_right) - break; - std::swap(__begin[__final_left], __begin[__final_right]); - ++__final_left; - --__final_right; - } - - // All elements on the left side are < piv, all elements on the - // right are >= piv - delete[] __reserved_left; - delete[] __reserved_right; - - omp_destroy_lock(&__result_lock); - - // Element "between" __final_left and __final_right might not have - // been regarded yet - if (__final_left < __n && !__pred(__begin[__final_left])) - // Really swapped. - return __final_left; - else - return __final_left + 1; - } - -/** - * @brief Parallel implementation of std::nth_element(). + __left = __leftnew; + __right = __rightnew; + } + +# pragma omp flush(__left, __right) + } // end "recursion" //parallel + + _DifferenceType __final_left = __left, __final_right = __right; + + while (__final_left < __final_right) + { + // Go right until key is geq than pivot. + while (__pred(__begin[__final_left]) + && __final_left < __final_right) + ++__final_left; + + // Go left until key is less than pivot. + while (!__pred(__begin[__final_right]) + && __final_left < __final_right) + --__final_right; + + if (__final_left == __final_right) + break; + std::swap(__begin[__final_left], __begin[__final_right]); + ++__final_left; + --__final_right; + } + + // All elements on the left side are < piv, all elements on the + // right are >= piv + delete[] __reserved_left; + delete[] __reserved_right; + + omp_destroy_lock(&__result_lock); + + // Element "between" __final_left and __final_right might not have + // been regarded yet + if (__final_left < __n && !__pred(__begin[__final_left])) + // Really swapped. + return __final_left; + else + return __final_left + 1; + } + + /** + * @brief Parallel implementation of std::nth_element(). + * @param __begin Begin iterator of input sequence. + * @param __nth _Iterator of element that must be in position afterwards. + * @param __end End iterator of input sequence. + * @param __comp Comparator. + */ + template<typename _RAIter, typename _Compare> + void + __parallel_nth_element(_RAIter __begin, _RAIter __nth, + _RAIter __end, _Compare __comp) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + + _GLIBCXX_CALL(__end - __begin) + + _RAIter __split; + _RandomNumber __rng; + + _DifferenceType __minimum_length = + std::max<_DifferenceType>(2, _Settings::get().partition_minimal_n); + + // Break if input range to small. + while (static_cast<_SequenceIndex>(__end - __begin) >= __minimum_length) + { + _DifferenceType __n = __end - __begin; + + _RAIter __pivot_pos = __begin + __rng(__n); + + // Swap __pivot_pos value to end. + if (__pivot_pos != (__end - 1)) + std::swap(*__pivot_pos, *(__end - 1)); + __pivot_pos = __end - 1; + + // _Compare must have first_value_type, second_value_type, + // result_type + // _Compare == + // __gnu_parallel::_Lexicographic<S, int, + // __gnu_parallel::_Less<S, S> > + // __pivot_pos == std::pair<S, int>* + __gnu_parallel::binder2nd<_Compare, _ValueType, _ValueType, bool> + __pred(__comp, *__pivot_pos); + + // Divide, leave pivot unchanged in last place. + _RAIter __split_pos1, __split_pos2; + __split_pos1 = __begin + __parallel_partition(__begin, __end - 1, + __pred, + __get_max_threads()); + + // Left side: < __pivot_pos; __right side: >= __pivot_pos + + // Swap pivot back to middle. + if (__split_pos1 != __pivot_pos) + std::swap(*__split_pos1, *__pivot_pos); + __pivot_pos = __split_pos1; + + // In case all elements are equal, __split_pos1 == 0 + if ((__split_pos1 + 1 - __begin) < (__n >> 7) + || (__end - __split_pos1) < (__n >> 7)) + { + // Very unequal split, one part smaller than one 128th + // elements not strictly larger than the pivot. + __gnu_parallel::__unary_negate<__gnu_parallel:: + __binder1st<_Compare, _ValueType, + _ValueType, bool>, _ValueType> + __pred(__gnu_parallel::__binder1st<_Compare, _ValueType, + _ValueType, bool>(__comp, *__pivot_pos)); + + // Find other end of pivot-equal range. + __split_pos2 = __gnu_sequential::partition(__split_pos1 + 1, + __end, __pred); + } + else + // Only skip the pivot. + __split_pos2 = __split_pos1 + 1; + + // Compare iterators. + if (__split_pos2 <= __nth) + __begin = __split_pos2; + else if (__nth < __split_pos1) + __end = __split_pos1; + else + break; + } + + // Only at most _Settings::partition_minimal_n __elements __left. + __gnu_sequential::sort(__begin, __end, __comp); + } + + /** @brief Parallel implementation of std::partial_sort(). * @param __begin Begin iterator of input sequence. - * @param __nth _Iterator of element that must be in position afterwards. + * @param __middle Sort until this position. * @param __end End iterator of input sequence. - * @param __comp Comparator. - */ -template<typename _RAIter, typename _Compare> - void - __parallel_nth_element(_RAIter __begin, _RAIter __nth, - _RAIter __end, _Compare __comp) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _GLIBCXX_CALL(__end - __begin) - - _RAIter __split; - _RandomNumber __rng; - - _DifferenceType __minimum_length = - std::max<_DifferenceType>(2, _Settings::get().partition_minimal_n); - - // Break if input range to small. - while (static_cast<_SequenceIndex>(__end - __begin) >= __minimum_length) - { - _DifferenceType __n = __end - __begin; - - _RAIter __pivot_pos = __begin + __rng(__n); - - // Swap __pivot_pos value to end. - if (__pivot_pos != (__end - 1)) - std::swap(*__pivot_pos, *(__end - 1)); - __pivot_pos = __end - 1; - - // _Compare must have first_value_type, second_value_type, - // result_type - // _Compare == - // __gnu_parallel::_Lexicographic<S, int, __gnu_parallel::_Less<S, S> > - // __pivot_pos == std::pair<S, int>* - __gnu_parallel::binder2nd<_Compare, _ValueType, _ValueType, bool> - __pred(__comp, *__pivot_pos); - - // Divide, leave pivot unchanged in last place. - _RAIter __split_pos1, __split_pos2; - __split_pos1 = __begin - + __parallel_partition(__begin, __end - 1, __pred, - __get_max_threads()); - - // Left side: < __pivot_pos; __right side: >= __pivot_pos - - // Swap pivot back to middle. - if (__split_pos1 != __pivot_pos) - std::swap(*__split_pos1, *__pivot_pos); - __pivot_pos = __split_pos1; - - // In case all elements are equal, __split_pos1 == 0 - if ((__split_pos1 + 1 - __begin) < (__n >> 7) - || (__end - __split_pos1) < (__n >> 7)) - { - // Very unequal split, one part smaller than one 128th - // elements not strictly larger than the pivot. - __gnu_parallel::__unary_negate<__gnu_parallel:: - __binder1st<_Compare, _ValueType, _ValueType, bool>, _ValueType> - __pred(__gnu_parallel::__binder1st<_Compare, _ValueType, - _ValueType, bool>(__comp, *__pivot_pos)); - - // Find other end of pivot-equal range. - __split_pos2 = __gnu_sequential::partition(__split_pos1 + 1, - __end, __pred); - } - else - // Only skip the pivot. - __split_pos2 = __split_pos1 + 1; - - // Compare iterators. - if (__split_pos2 <= __nth) - __begin = __split_pos2; - else if (__nth < __split_pos1) - __end = __split_pos1; - else - break; - } - - // Only at most _Settings::partition_minimal_n __elements __left. - __gnu_sequential::sort(__begin, __end, __comp); - } - -/** @brief Parallel implementation of std::partial_sort(). -* @param __begin Begin iterator of input sequence. -* @param __middle Sort until this position. -* @param __end End iterator of input sequence. -* @param __comp Comparator. */ -template<typename _RAIter, typename _Compare> - void - __parallel_partial_sort(_RAIter __begin, - _RAIter __middle, - _RAIter __end, _Compare __comp) - { - __parallel_nth_element(__begin, __middle, __end, __comp); - std::sort(__begin, __middle, __comp); - } + * @param __comp Comparator. */ + template<typename _RAIter, typename _Compare> + void + __parallel_partial_sort(_RAIter __begin, + _RAIter __middle, + _RAIter __end, _Compare __comp) + { + __parallel_nth_element(__begin, __middle, __end, __comp); + std::sort(__begin, __middle, __comp); + } } //namespace __gnu_parallel diff --git a/libstdc++-v3/include/parallel/queue.h b/libstdc++-v3/include/parallel/queue.h index 348bb1ac900..28c78600860 100644 --- a/libstdc++-v3/include/parallel/queue.h +++ b/libstdc++-v3/include/parallel/queue.h @@ -45,7 +45,7 @@ namespace __gnu_parallel * atomic access. push_front() and pop_front() must not be called * concurrently to each other, while pop_back() can be called * concurrently at all times. - * @__c empty(), @__c size(), and @__c top() are intentionally not provided. + * @c empty(), @c size(), and @c top() are intentionally not provided. * Calling them would not make sense in a concurrent setting. * @param _Tp Contained element type. */ template<typename _Tp> @@ -65,10 +65,10 @@ namespace __gnu_parallel public: /** @brief Constructor. Not to be called concurrent, of course. * @param _M_max_size Maximal number of elements to be contained. */ - _RestrictedBoundedConcurrentQueue(_SequenceIndex _M_max_size) + _RestrictedBoundedConcurrentQueue(_SequenceIndex __max_size) { - this->_M_max_size = _M_max_size; - _M_base = new _Tp[_M_max_size]; + _M_max_size = __max_size; + _M_base = new _Tp[__max_size]; _M_borders = __encode2(0, 0); #pragma omp flush } @@ -105,12 +105,12 @@ namespace __gnu_parallel while (__former_front > __former_back) { // Chance. - _CASable - __former_borders = __encode2(__former_front, __former_back); - _CASable - __new_borders = __encode2(__former_front - 1, __former_back); - if (__compare_and_swap( - &_M_borders, __former_borders, __new_borders)) + _CASable __former_borders = __encode2(__former_front, + __former_back); + _CASable __new_borders = __encode2(__former_front - 1, + __former_back); + if (__compare_and_swap(&_M_borders, __former_borders, + __new_borders)) { __t = *(_M_base + (__former_front - 1) % _M_max_size); return true; @@ -132,12 +132,12 @@ namespace __gnu_parallel while (__former_front > __former_back) { // Chance. - _CASable - __former_borders = __encode2(__former_front, __former_back); - _CASable - __new_borders = __encode2(__former_front, __former_back + 1); - if (__compare_and_swap( - &_M_borders, __former_borders, __new_borders)) + _CASable __former_borders = __encode2(__former_front, + __former_back); + _CASable __new_borders = __encode2(__former_front, + __former_back + 1); + if (__compare_and_swap(&_M_borders, __former_borders, + __new_borders)) { __t = *(_M_base + __former_back % _M_max_size); return true; diff --git a/libstdc++-v3/include/parallel/quicksort.h b/libstdc++-v3/include/parallel/quicksort.h index 1ed46b4a77f..508c3c1763c 100644 --- a/libstdc++-v3/include/parallel/quicksort.h +++ b/libstdc++-v3/include/parallel/quicksort.h @@ -48,13 +48,12 @@ namespace __gnu_parallel */ template<typename _RAIter, typename _Compare> typename std::iterator_traits<_RAIter>::difference_type - __parallel_sort_qs_divide(_RAIter __begin, - _RAIter __end, - _Compare __comp, typename std::iterator_traits - <_RAIter>::difference_type __pivot_rank, - typename std::iterator_traits - <_RAIter>::difference_type - __num_samples, _ThreadIndex __num_threads) + __parallel_sort_qs_divide(_RAIter __begin, _RAIter __end, + _Compare __comp, typename std::iterator_traits + <_RAIter>::difference_type __pivot_rank, + typename std::iterator_traits + <_RAIter>::difference_type + __num_samples, _ThreadIndex __num_threads) { typedef std::iterator_traits<_RAIter> _TraitsType; typedef typename _TraitsType::value_type _ValueType; @@ -64,25 +63,24 @@ namespace __gnu_parallel __num_samples = std::min(__num_samples, __n); // Allocate uninitialized, to avoid default constructor. - _ValueType* __samples = - static_cast<_ValueType*>(::operator new(__num_samples - * sizeof(_ValueType))); + _ValueType* __samples = static_cast<_ValueType*> + (::operator new(__num_samples * sizeof(_ValueType))); for (_DifferenceType __s = 0; __s < __num_samples; ++__s) { - const unsigned long long __index - = static_cast<unsigned long long>(__s) * __n / __num_samples; + const unsigned long long __index = static_cast<unsigned long long> + (__s) * __n / __num_samples; ::new(&(__samples[__s])) _ValueType(__begin[__index]); } __gnu_sequential::sort(__samples, __samples + __num_samples, __comp); - _ValueType& pivot = __samples[__pivot_rank * __num_samples / __n]; + _ValueType& __pivot = __samples[__pivot_rank * __num_samples / __n]; __gnu_parallel::binder2nd<_Compare, _ValueType, _ValueType, bool> - __pred(__comp, pivot); - _DifferenceType __split = - __parallel_partition(__begin, __end, __pred, __num_threads); + __pred(__comp, __pivot); + _DifferenceType __split = __parallel_partition(__begin, __end, + __pred, __num_threads); ::operator delete(__samples); @@ -98,10 +96,9 @@ namespace __gnu_parallel */ template<typename _RAIter, typename _Compare> void - __parallel_sort_qs_conquer(_RAIter __begin, - _RAIter __end, - _Compare __comp, - _ThreadIndex __num_threads) + __parallel_sort_qs_conquer(_RAIter __begin, _RAIter __end, + _Compare __comp, + _ThreadIndex __num_threads) { typedef std::iterator_traits<_RAIter> _TraitsType; typedef typename _TraitsType::value_type _ValueType; @@ -127,24 +124,22 @@ namespace __gnu_parallel __pivot_rank = __n * __num_threads_left / __num_threads; - _DifferenceType __split = - __parallel_sort_qs_divide(__begin, __end, __comp, __pivot_rank, - _Settings::get().sort_qs_num_samples_preset, - __num_threads); + _DifferenceType __split = __parallel_sort_qs_divide + (__begin, __end, __comp, __pivot_rank, + _Settings::get().sort_qs_num_samples_preset, __num_threads); #pragma omp parallel sections num_threads(2) { #pragma omp section __parallel_sort_qs_conquer(__begin, __begin + __split, - __comp, __num_threads_left); + __comp, __num_threads_left); #pragma omp section __parallel_sort_qs_conquer(__begin + __split, __end, - __comp, __num_threads - __num_threads_left); + __comp, __num_threads - __num_threads_left); } } - /** @brief Unbalanced quicksort main call. * @param __begin Begin iterator of input sequence. * @param __end End iterator input sequence, ignored. @@ -154,10 +149,9 @@ namespace __gnu_parallel */ template<typename _RAIter, typename _Compare> void - __parallel_sort_qs(_RAIter __begin, - _RAIter __end, - _Compare __comp, - _ThreadIndex __num_threads) + __parallel_sort_qs(_RAIter __begin, _RAIter __end, + _Compare __comp, + _ThreadIndex __num_threads) { _GLIBCXX_CALL(__n) diff --git a/libstdc++-v3/include/parallel/random_number.h b/libstdc++-v3/include/parallel/random_number.h index 4df91df0583..c39f15e1298 100644 --- a/libstdc++-v3/include/parallel/random_number.h +++ b/libstdc++-v3/include/parallel/random_number.h @@ -81,7 +81,7 @@ namespace __gnu_parallel /** @brief Constructor. * @param __seed Random __seed. * @param _M_supremum Generate integer random numbers in the - * interval @__c [0,_M_supremum). */ + * interval @c [0,_M_supremum). */ _RandomNumber(uint32_t __seed, uint64_t _M_supremum = 0x100000000ULL) : _M_mt(__seed), _M_supremum(_M_supremum), _M_rand_sup(1ULL << std::numeric_limits<uint32_t>::digits), @@ -95,7 +95,7 @@ namespace __gnu_parallel { return __scale_down(_M_mt(), _M_supremum, _M_supremum_reciprocal); } /** @brief Generate unsigned random 32-bit integer in the - interval @__c [0,local_supremum). */ + interval @c [0,local_supremum). */ uint32_t operator()(uint64_t local_supremum) { diff --git a/libstdc++-v3/include/parallel/random_shuffle.h b/libstdc++-v3/include/parallel/random_shuffle.h index a74b9ac82ac..3082ea8dbc0 100644 --- a/libstdc++-v3/include/parallel/random_shuffle.h +++ b/libstdc++-v3/include/parallel/random_shuffle.h @@ -39,492 +39,484 @@ namespace __gnu_parallel { -/** @brief Type to hold the index of a bin. - * - * Since many variables of this type are allocated, it should be - * chosen as small as possible. - */ -typedef unsigned short _BinIndex; - -/** @brief Data known to every thread participating in - __gnu_parallel::__parallel_random_shuffle(). */ -template<typename _RAIter> - struct _DRandomShufflingGlobalData - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - /** @brief Begin iterator of the __source. */ - _RAIter& _M_source; - - /** @brief Temporary arrays for each thread. */ - _ValueType** _M_temporaries; - - /** @brief Two-dimensional array to hold the thread-bin distribution. - * - * Dimensions (_M_num_threads + 1) __x (_M_num_bins + 1). */ - _DifferenceType** _M_dist; - - /** @brief Start indexes of the threads' __chunks. */ - _DifferenceType* _M_starts; - - /** @brief Number of the thread that will further process the - corresponding bin. */ - _ThreadIndex* _M_bin_proc; - - /** @brief Number of bins to distribute to. */ - int _M_num_bins; - - /** @brief Number of bits needed to address the bins. */ - int _M_num_bits; - - /** @brief Constructor. */ - _DRandomShufflingGlobalData(_RAIter& __source) - : _M_source(__source) { } - }; - -/** @brief Local data for a thread participating in - __gnu_parallel::__parallel_random_shuffle(). - */ -template<typename _RAIter, typename _RandomNumberGenerator> - struct _DRSSorterPU - { - /** @brief Number of threads participating in total. */ - int _M_num_threads; - - /** @brief Begin index for bins taken care of by this thread. */ - _BinIndex _M_bins_begin; - - /** @brief End index for bins taken care of by this thread. */ - _BinIndex __bins_end; - - /** @brief Random _M_seed for this thread. */ - uint32_t _M_seed; - - /** @brief Pointer to global data. */ - _DRandomShufflingGlobalData<_RAIter>* _M_sd; - }; - -/** @brief Generate a random number in @__c [0,2^logp). - * @param logp Logarithm (basis 2) of the upper range __bound. - * @param __rng Random number generator to use. - */ -template<typename _RandomNumberGenerator> - inline int - __random_number_pow2(int logp, _RandomNumberGenerator& __rng) - { return __rng.__genrand_bits(logp); } - -/** @brief Random shuffle code executed by each thread. - * @param __pus Array of thread-local data records. */ -template<typename _RAIter, typename _RandomNumberGenerator> - void - __parallel_random_shuffle_drs_pu(_DRSSorterPU<_RAIter, - _RandomNumberGenerator>* __pus) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _ThreadIndex __iam = omp_get_thread_num(); - _DRSSorterPU<_RAIter, _RandomNumberGenerator>* d = &__pus[__iam]; - _DRandomShufflingGlobalData<_RAIter>* _M_sd = d->_M_sd; - - // Indexing: _M_dist[bin][processor] - _DifferenceType __length = _M_sd->_M_starts[__iam + 1] - - _M_sd->_M_starts[__iam]; - _BinIndex* __oracles = new _BinIndex[__length]; - _DifferenceType* _M_dist = new _DifferenceType[_M_sd->_M_num_bins + 1]; - _BinIndex* _M_bin_proc = new _BinIndex[_M_sd->_M_num_bins]; - _ValueType** _M_temporaries = new _ValueType*[d->_M_num_threads]; - - // Compute oracles and count appearances. - for (_BinIndex __b = 0; __b < _M_sd->_M_num_bins + 1; ++__b) - _M_dist[__b] = 0; - int _M_num_bits = _M_sd->_M_num_bits; - - _RandomNumber __rng(d->_M_seed); - - // First main loop. - for (_DifferenceType __i = 0; __i < __length; ++__i) - { - _BinIndex __oracle = __random_number_pow2(_M_num_bits, __rng); - __oracles[__i] = __oracle; + /** @brief Type to hold the index of a bin. + * + * Since many variables of this type are allocated, it should be + * chosen as small as possible. + */ + typedef unsigned short _BinIndex; + + /** @brief Data known to every thread participating in + __gnu_parallel::__parallel_random_shuffle(). */ + template<typename _RAIter> + struct _DRandomShufflingGlobalData + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; - // To allow prefix (partial) sum. - ++(_M_dist[__oracle + 1]); - } + /** @brief Begin iterator of the __source. */ + _RAIter& _M_source; - for (_BinIndex __b = 0; __b < _M_sd->_M_num_bins + 1; ++__b) - _M_sd->_M_dist[__b][__iam + 1] = _M_dist[__b]; + /** @brief Temporary arrays for each thread. */ + _ValueType** _M_temporaries; -# pragma omp barrier + /** @brief Two-dimensional array to hold the thread-bin distribution. + * + * Dimensions (_M_num_threads + 1) __x (_M_num_bins + 1). */ + _DifferenceType** _M_dist; -# pragma omp single - { - // Sum up bins, _M_sd->_M_dist[__s + 1][d->_M_num_threads] now contains - // the total number of items in bin __s - for (_BinIndex __s = 0; __s < _M_sd->_M_num_bins; ++__s) - __gnu_sequential::partial_sum( - _M_sd->_M_dist[__s + 1], - _M_sd->_M_dist[__s + 1] + d->_M_num_threads + 1, - _M_sd->_M_dist[__s + 1]); - } + /** @brief Start indexes of the threads' __chunks. */ + _DifferenceType* _M_starts; -# pragma omp barrier + /** @brief Number of the thread that will further process the + corresponding bin. */ + _ThreadIndex* _M_bin_proc; - _SequenceIndex __offset = 0, __global_offset = 0; - for (_BinIndex __s = 0; __s < d->_M_bins_begin; ++__s) - __global_offset += _M_sd->_M_dist[__s + 1][d->_M_num_threads]; + /** @brief Number of bins to distribute to. */ + int _M_num_bins; -# pragma omp barrier + /** @brief Number of bits needed to address the bins. */ + int _M_num_bits; - for (_BinIndex __s = d->_M_bins_begin; __s < d->__bins_end; ++__s) - { - for (int __t = 0; __t < d->_M_num_threads + 1; ++__t) - _M_sd->_M_dist[__s + 1][__t] += __offset; - __offset = _M_sd->_M_dist[__s + 1][d->_M_num_threads]; - } + /** @brief Constructor. */ + _DRandomShufflingGlobalData(_RAIter& __source) + : _M_source(__source) { } + }; + + /** @brief Local data for a thread participating in + __gnu_parallel::__parallel_random_shuffle(). + */ + template<typename _RAIter, typename _RandomNumberGenerator> + struct _DRSSorterPU + { + /** @brief Number of threads participating in total. */ + int _M_num_threads; + + /** @brief Begin index for bins taken care of by this thread. */ + _BinIndex _M_bins_begin; + + /** @brief End index for bins taken care of by this thread. */ + _BinIndex __bins_end; + + /** @brief Random _M_seed for this thread. */ + uint32_t _M_seed; + + /** @brief Pointer to global data. */ + _DRandomShufflingGlobalData<_RAIter>* _M_sd; + }; + + /** @brief Generate a random number in @c [0,2^__logp). + * @param __logp Logarithm (basis 2) of the upper range __bound. + * @param __rng Random number generator to use. + */ + template<typename _RandomNumberGenerator> + inline int + __random_number_pow2(int __logp, _RandomNumberGenerator& __rng) + { return __rng.__genrand_bits(__logp); } + + /** @brief Random shuffle code executed by each thread. + * @param __pus Array of thread-local data records. */ + template<typename _RAIter, typename _RandomNumberGenerator> + void + __parallel_random_shuffle_drs_pu(_DRSSorterPU<_RAIter, + _RandomNumberGenerator>* __pus) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; - _M_sd->_M_temporaries[__iam] = static_cast<_ValueType*>( - ::operator new(sizeof(_ValueType) * __offset)); + _ThreadIndex __iam = omp_get_thread_num(); + _DRSSorterPU<_RAIter, _RandomNumberGenerator>* __d = &__pus[__iam]; + _DRandomShufflingGlobalData<_RAIter>* __sd = __d->_M_sd; -# pragma omp barrier + // Indexing: _M_dist[bin][processor] + _DifferenceType __length = (__sd->_M_starts[__iam + 1] + - __sd->_M_starts[__iam]); + _BinIndex* __oracles = new _BinIndex[__length]; + _DifferenceType* __dist = new _DifferenceType[__sd->_M_num_bins + 1]; + _BinIndex* __bin_proc = new _BinIndex[__sd->_M_num_bins]; + _ValueType** __temporaries = new _ValueType*[__d->_M_num_threads]; - // Draw local copies to avoid false sharing. - for (_BinIndex __b = 0; __b < _M_sd->_M_num_bins + 1; ++__b) - _M_dist[__b] = _M_sd->_M_dist[__b][__iam]; - for (_BinIndex __b = 0; __b < _M_sd->_M_num_bins; ++__b) - _M_bin_proc[__b] = _M_sd->_M_bin_proc[__b]; - for (_ThreadIndex __t = 0; __t < d->_M_num_threads; ++__t) - _M_temporaries[__t] = _M_sd->_M_temporaries[__t]; + // Compute oracles and count appearances. + for (_BinIndex __b = 0; __b < __sd->_M_num_bins + 1; ++__b) + __dist[__b] = 0; + int __num_bits = __sd->_M_num_bits; - _RAIter _M_source = _M_sd->_M_source; - _DifferenceType __start = _M_sd->_M_starts[__iam]; + _RandomNumber __rng(__d->_M_seed); - // Distribute according to oracles, second main loop. - for (_DifferenceType __i = 0; __i < __length; ++__i) - { - _BinIndex target_bin = __oracles[__i]; - _ThreadIndex target_p = _M_bin_proc[target_bin]; + // First main loop. + for (_DifferenceType __i = 0; __i < __length; ++__i) + { + _BinIndex __oracle = __random_number_pow2(__num_bits, __rng); + __oracles[__i] = __oracle; - // Last column [d->_M_num_threads] stays unchanged. - ::new(&(_M_temporaries[target_p][_M_dist[target_bin + 1]++])) - _ValueType(*(_M_source + __i + __start)); - } + // To allow prefix (partial) sum. + ++(__dist[__oracle + 1]); + } - delete[] __oracles; - delete[] _M_dist; - delete[] _M_bin_proc; - delete[] _M_temporaries; + for (_BinIndex __b = 0; __b < __sd->_M_num_bins + 1; ++__b) + __sd->_M_dist[__b][__iam + 1] = __dist[__b]; -# pragma omp barrier +# pragma omp barrier - // Shuffle bins internally. - for (_BinIndex __b = d->_M_bins_begin; __b < d->__bins_end; ++__b) +# pragma omp single { - _ValueType* __begin = - _M_sd->_M_temporaries[__iam] + - ((__b == d->_M_bins_begin) - ? 0 : _M_sd->_M_dist[__b][d->_M_num_threads]), - * __end = - _M_sd->_M_temporaries[__iam] + - _M_sd->_M_dist[__b + 1][d->_M_num_threads]; - __sequential_random_shuffle(__begin, __end, __rng); - std::copy(__begin, __end, _M_sd->_M_source + __global_offset + - ((__b == d->_M_bins_begin) - ? 0 : _M_sd->_M_dist[__b][d->_M_num_threads])); + // Sum up bins, __sd->_M_dist[__s + 1][__d->_M_num_threads] now + // contains the total number of items in bin __s + for (_BinIndex __s = 0; __s < __sd->_M_num_bins; ++__s) + __gnu_sequential::partial_sum(__sd->_M_dist[__s + 1], + __sd->_M_dist[__s + 1] + + __d->_M_num_threads + 1, + __sd->_M_dist[__s + 1]); } - ::operator delete(_M_sd->_M_temporaries[__iam]); - } - -/** @brief Round up to the next greater power of 2. - * @param __x _Integer to round up */ -template<typename _Tp> - _Tp - __round_up_to_pow2(_Tp __x) - { - if (__x <= 1) - return 1; - else - return (_Tp)1 << (__rd_log2(__x - 1) + 1); - } - -/** @brief Main parallel random shuffle step. - * @param __begin Begin iterator of sequence. - * @param __end End iterator of sequence. - * @param __n Length of sequence. - * @param __num_threads Number of threads to use. - * @param __rng Random number generator to use. - */ -template<typename _RAIter, typename _RandomNumberGenerator> - void - __parallel_random_shuffle_drs(_RAIter __begin, - _RAIter __end, - typename std::iterator_traits - <_RAIter>::difference_type __n, - _ThreadIndex __num_threads, - _RandomNumberGenerator& __rng) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _GLIBCXX_CALL(__n) - - const _Settings& __s = _Settings::get(); - - if (__num_threads > __n) - __num_threads = static_cast<_ThreadIndex>(__n); - - _BinIndex _M_num_bins, __num_bins_cache; +# pragma omp barrier + + _SequenceIndex __offset = 0, __global_offset = 0; + for (_BinIndex __s = 0; __s < __d->_M_bins_begin; ++__s) + __global_offset += __sd->_M_dist[__s + 1][__d->_M_num_threads]; + +# pragma omp barrier + + for (_BinIndex __s = __d->_M_bins_begin; __s < __d->__bins_end; ++__s) + { + for (int __t = 0; __t < __d->_M_num_threads + 1; ++__t) + __sd->_M_dist[__s + 1][__t] += __offset; + __offset = __sd->_M_dist[__s + 1][__d->_M_num_threads]; + } + + __sd->_M_temporaries[__iam] = static_cast<_ValueType*> + (::operator new(sizeof(_ValueType) * __offset)); + +# pragma omp barrier + + // Draw local copies to avoid false sharing. + for (_BinIndex __b = 0; __b < __sd->_M_num_bins + 1; ++__b) + __dist[__b] = __sd->_M_dist[__b][__iam]; + for (_BinIndex __b = 0; __b < __sd->_M_num_bins; ++__b) + __bin_proc[__b] = __sd->_M_bin_proc[__b]; + for (_ThreadIndex __t = 0; __t < __d->_M_num_threads; ++__t) + __temporaries[__t] = __sd->_M_temporaries[__t]; + + _RAIter __source = __sd->_M_source; + _DifferenceType __start = __sd->_M_starts[__iam]; + + // Distribute according to oracles, second main loop. + for (_DifferenceType __i = 0; __i < __length; ++__i) + { + _BinIndex __target_bin = __oracles[__i]; + _ThreadIndex __target_p = __bin_proc[__target_bin]; + + // Last column [__d->_M_num_threads] stays unchanged. + ::new(&(__temporaries[__target_p][__dist[__target_bin + 1]++])) + _ValueType(*(__source + __i + __start)); + } + + delete[] __oracles; + delete[] __dist; + delete[] __bin_proc; + delete[] __temporaries; + +# pragma omp barrier + + // Shuffle bins internally. + for (_BinIndex __b = __d->_M_bins_begin; __b < __d->__bins_end; ++__b) + { + _ValueType* __begin = + (__sd->_M_temporaries[__iam] + + (__b == __d->_M_bins_begin + ? 0 : __sd->_M_dist[__b][__d->_M_num_threads])), + * __end = (__sd->_M_temporaries[__iam] + + __sd->_M_dist[__b + 1][__d->_M_num_threads]); + + __sequential_random_shuffle(__begin, __end, __rng); + std::copy(__begin, __end, __sd->_M_source + __global_offset + + (__b == __d->_M_bins_begin + ? 0 : __sd->_M_dist[__b][__d->_M_num_threads])); + } + + ::operator delete(__sd->_M_temporaries[__iam]); + } + + /** @brief Round up to the next greater power of 2. + * @param __x _Integer to round up */ + template<typename _Tp> + _Tp + __round_up_to_pow2(_Tp __x) + { + if (__x <= 1) + return 1; + else + return (_Tp)1 << (__rd_log2(__x - 1) + 1); + } + + /** @brief Main parallel random shuffle step. + * @param __begin Begin iterator of sequence. + * @param __end End iterator of sequence. + * @param __n Length of sequence. + * @param __num_threads Number of threads to use. + * @param __rng Random number generator to use. + */ + template<typename _RAIter, typename _RandomNumberGenerator> + void + __parallel_random_shuffle_drs(_RAIter __begin, _RAIter __end, + typename std::iterator_traits + <_RAIter>::difference_type __n, + _ThreadIndex __num_threads, + _RandomNumberGenerator& __rng) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + + _GLIBCXX_CALL(__n) + + const _Settings& __s = _Settings::get(); + + if (__num_threads > __n) + __num_threads = static_cast<_ThreadIndex>(__n); + + _BinIndex __num_bins, __num_bins_cache; #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1 - // Try the L1 cache first. + // Try the L1 cache first. - // Must fit into L1. - __num_bins_cache = std::max<_DifferenceType>( - 1, __n / (__s.L1_cache_size_lb / sizeof(_ValueType))); - __num_bins_cache = __round_up_to_pow2(__num_bins_cache); + // Must fit into L1. + __num_bins_cache = + std::max<_DifferenceType>(1, __n / (__s.L1_cache_size_lb + / sizeof(_ValueType))); + __num_bins_cache = __round_up_to_pow2(__num_bins_cache); - // No more buckets than TLB entries, power of 2 - // Power of 2 and at least one element per bin, at most the TLB size. - _M_num_bins = std::min<_DifferenceType>(__n, __num_bins_cache); + // No more buckets than TLB entries, power of 2 + // Power of 2 and at least one element per bin, at most the TLB size. + __num_bins = std::min<_DifferenceType>(__n, __num_bins_cache); #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB - // 2 TLB entries needed per bin. - _M_num_bins = std::min<_DifferenceType>(__s.TLB_size / 2, _M_num_bins); + // 2 TLB entries needed per bin. + __num_bins = std::min<_DifferenceType>(__s.TLB_size / 2, __num_bins); #endif - _M_num_bins = __round_up_to_pow2(_M_num_bins); + __num_bins = __round_up_to_pow2(__num_bins); - if (_M_num_bins < __num_bins_cache) - { + if (__num_bins < __num_bins_cache) + { #endif - // Now try the L2 cache - // Must fit into L2 - __num_bins_cache = static_cast<_BinIndex>(std::max<_DifferenceType>( - 1, __n / (__s.L2_cache_size / sizeof(_ValueType)))); - __num_bins_cache = __round_up_to_pow2(__num_bins_cache); - - // No more buckets than TLB entries, power of 2. - _M_num_bins = static_cast<_BinIndex>( - std::min(__n, static_cast<_DifferenceType>(__num_bins_cache))); - // Power of 2 and at least one element per bin, at most the TLB size. + // Now try the L2 cache + // Must fit into L2 + __num_bins_cache = static_cast<_BinIndex> + (std::max<_DifferenceType>(1, __n / (__s.L2_cache_size + / sizeof(_ValueType)))); + __num_bins_cache = __round_up_to_pow2(__num_bins_cache); + + // No more buckets than TLB entries, power of 2. + __num_bins = static_cast<_BinIndex> + (std::min(__n, static_cast<_DifferenceType>(__num_bins_cache))); + // Power of 2 and at least one element per bin, at most the TLB size. #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB - // 2 TLB entries needed per bin. - _M_num_bins = std::min( - static_cast<_DifferenceType>(__s.TLB_size / 2), _M_num_bins); + // 2 TLB entries needed per bin. + __num_bins = std::min(static_cast<_DifferenceType>(__s.TLB_size / 2), + __num_bins); #endif - _M_num_bins = __round_up_to_pow2(_M_num_bins); + __num_bins = __round_up_to_pow2(__num_bins); #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1 - } + } #endif - __num_threads = std::min<_BinIndex>(__num_threads, _M_num_bins); + __num_threads = std::min<_BinIndex>(__num_threads, __num_bins); - if (__num_threads <= 1) - return __sequential_random_shuffle(__begin, __end, __rng); + if (__num_threads <= 1) + return __sequential_random_shuffle(__begin, __end, __rng); - _DRandomShufflingGlobalData<_RAIter> _M_sd(__begin); - _DRSSorterPU<_RAIter, _RandomNumber >* __pus; - _DifferenceType* _M_starts; + _DRandomShufflingGlobalData<_RAIter> __sd(__begin); + _DRSSorterPU<_RAIter, _RandomNumber >* __pus; + _DifferenceType* __starts; -# pragma omp parallel num_threads(__num_threads) +# pragma omp parallel num_threads(__num_threads) { - _ThreadIndex __num_threads = omp_get_num_threads(); + _ThreadIndex __num_threads = omp_get_num_threads(); # pragma omp single - { - __pus = new _DRSSorterPU<_RAIter, _RandomNumber> - [__num_threads]; - - _M_sd._M_temporaries = new _ValueType*[__num_threads]; - _M_sd._M_dist = new _DifferenceType*[_M_num_bins + 1]; - _M_sd._M_bin_proc = new _ThreadIndex[_M_num_bins]; - for (_BinIndex __b = 0; __b < _M_num_bins + 1; ++__b) - _M_sd._M_dist[__b] = new _DifferenceType[__num_threads + 1]; - for (_BinIndex __b = 0; __b < (_M_num_bins + 1); ++__b) - { - _M_sd._M_dist[0][0] = 0; - _M_sd._M_dist[__b][0] = 0; - } - _M_starts = _M_sd._M_starts - = new _DifferenceType[__num_threads + 1]; - int bin_cursor = 0; - _M_sd._M_num_bins = _M_num_bins; - _M_sd._M_num_bits = __rd_log2(_M_num_bins); - - _DifferenceType __chunk_length = __n / __num_threads, - __split = __n % __num_threads, __start = 0; - _DifferenceType bin_chunk_length = _M_num_bins / __num_threads, - bin_split = _M_num_bins % __num_threads; - for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) - { - _M_starts[__i] = __start; - __start += (__i < __split) - ? (__chunk_length + 1) : __chunk_length; - int __j = __pus[__i]._M_bins_begin = bin_cursor; - - // Range of bins for this processor. - bin_cursor += (__i < bin_split) ? - (bin_chunk_length + 1) : bin_chunk_length; - __pus[__i].__bins_end = bin_cursor; - for (; __j < bin_cursor; ++__j) - _M_sd._M_bin_proc[__j] = __i; - __pus[__i]._M_num_threads = __num_threads; - __pus[__i]._M_seed = - __rng(std::numeric_limits<uint32_t>::max()); - __pus[__i]._M_sd = &_M_sd; - } - _M_starts[__num_threads] = __start; - } //single - // Now shuffle in parallel. - __parallel_random_shuffle_drs_pu(__pus); + { + __pus = new _DRSSorterPU<_RAIter, _RandomNumber>[__num_threads]; + + __sd._M_temporaries = new _ValueType*[__num_threads]; + __sd._M_dist = new _DifferenceType*[__num_bins + 1]; + __sd._M_bin_proc = new _ThreadIndex[__num_bins]; + for (_BinIndex __b = 0; __b < __num_bins + 1; ++__b) + __sd._M_dist[__b] = new _DifferenceType[__num_threads + 1]; + for (_BinIndex __b = 0; __b < (__num_bins + 1); ++__b) + { + __sd._M_dist[0][0] = 0; + __sd._M_dist[__b][0] = 0; + } + __starts = __sd._M_starts = new _DifferenceType[__num_threads + 1]; + int __bin_cursor = 0; + __sd._M_num_bins = __num_bins; + __sd._M_num_bits = __rd_log2(__num_bins); + + _DifferenceType __chunk_length = __n / __num_threads, + __split = __n % __num_threads, + __start = 0; + _DifferenceType __bin_chunk_length = __num_bins / __num_threads, + __bin_split = __num_bins % __num_threads; + for (_ThreadIndex __i = 0; __i < __num_threads; ++__i) + { + __starts[__i] = __start; + __start += (__i < __split + ? (__chunk_length + 1) : __chunk_length); + int __j = __pus[__i]._M_bins_begin = __bin_cursor; + + // Range of bins for this processor. + __bin_cursor += (__i < __bin_split + ? (__bin_chunk_length + 1) + : __bin_chunk_length); + __pus[__i].__bins_end = __bin_cursor; + for (; __j < __bin_cursor; ++__j) + __sd._M_bin_proc[__j] = __i; + __pus[__i]._M_num_threads = __num_threads; + __pus[__i]._M_seed = __rng(std::numeric_limits<uint32_t>::max()); + __pus[__i]._M_sd = &__sd; + } + __starts[__num_threads] = __start; + } //single + // Now shuffle in parallel. + __parallel_random_shuffle_drs_pu(__pus); } // parallel - delete[] _M_starts; - delete[] _M_sd._M_bin_proc; - for (int __s = 0; __s < (_M_num_bins + 1); ++__s) - delete[] _M_sd._M_dist[__s]; - delete[] _M_sd._M_dist; - delete[] _M_sd._M_temporaries; + delete[] __starts; + delete[] __sd._M_bin_proc; + for (int __s = 0; __s < (__num_bins + 1); ++__s) + delete[] __sd._M_dist[__s]; + delete[] __sd._M_dist; + delete[] __sd._M_temporaries; - delete[] __pus; - } + delete[] __pus; + } -/** @brief Sequential cache-efficient random shuffle. - * @param __begin Begin iterator of sequence. - * @param __end End iterator of sequence. - * @param __rng Random number generator to use. - */ -template<typename _RAIter, typename _RandomNumberGenerator> - void - __sequential_random_shuffle(_RAIter __begin, - _RAIter __end, - _RandomNumberGenerator& __rng) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; + /** @brief Sequential cache-efficient random shuffle. + * @param __begin Begin iterator of sequence. + * @param __end End iterator of sequence. + * @param __rng Random number generator to use. + */ + template<typename _RAIter, typename _RandomNumberGenerator> + void + __sequential_random_shuffle(_RAIter __begin, _RAIter __end, + _RandomNumberGenerator& __rng) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; - _DifferenceType __n = __end - __begin; - const _Settings& __s = _Settings::get(); + _DifferenceType __n = __end - __begin; + const _Settings& __s = _Settings::get(); - _BinIndex _M_num_bins, __num_bins_cache; + _BinIndex __num_bins, __num_bins_cache; #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1 - // Try the L1 cache first, must fit into L1. - __num_bins_cache = - std::max<_DifferenceType> - (1, __n / (__s.L1_cache_size_lb / sizeof(_ValueType))); - __num_bins_cache = __round_up_to_pow2(__num_bins_cache); - - // No more buckets than TLB entries, power of 2 - // Power of 2 and at least one element per bin, at most the TLB size - _M_num_bins = std::min(__n, (_DifferenceType)__num_bins_cache); + // Try the L1 cache first, must fit into L1. + __num_bins_cache = std::max<_DifferenceType> + (1, __n / (__s.L1_cache_size_lb / sizeof(_ValueType))); + __num_bins_cache = __round_up_to_pow2(__num_bins_cache); + + // No more buckets than TLB entries, power of 2 + // Power of 2 and at least one element per bin, at most the TLB size + __num_bins = std::min(__n, (_DifferenceType)__num_bins_cache); #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB - // 2 TLB entries needed per bin - _M_num_bins = std::min((_DifferenceType)__s.TLB_size / 2, _M_num_bins); + // 2 TLB entries needed per bin + __num_bins = std::min((_DifferenceType)__s.TLB_size / 2, __num_bins); #endif - _M_num_bins = __round_up_to_pow2(_M_num_bins); + __num_bins = __round_up_to_pow2(__num_bins); - if (_M_num_bins < __num_bins_cache) - { + if (__num_bins < __num_bins_cache) + { #endif - // Now try the L2 cache, must fit into L2. - __num_bins_cache = - static_cast<_BinIndex>(std::max<_DifferenceType>( - 1, __n / (__s.L2_cache_size / sizeof(_ValueType)))); - __num_bins_cache = __round_up_to_pow2(__num_bins_cache); + // Now try the L2 cache, must fit into L2. + __num_bins_cache = static_cast<_BinIndex> + (std::max<_DifferenceType>(1, __n / (__s.L2_cache_size + / sizeof(_ValueType)))); + __num_bins_cache = __round_up_to_pow2(__num_bins_cache); - // No more buckets than TLB entries, power of 2 - // Power of 2 and at least one element per bin, at most the TLB size. - _M_num_bins = static_cast<_BinIndex> - (std::min(__n, static_cast<_DifferenceType>(__num_bins_cache))); + // No more buckets than TLB entries, power of 2 + // Power of 2 and at least one element per bin, at most the TLB size. + __num_bins = static_cast<_BinIndex> + (std::min(__n, static_cast<_DifferenceType>(__num_bins_cache))); #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB - // 2 TLB entries needed per bin - _M_num_bins = - std::min<_DifferenceType>(__s.TLB_size / 2, _M_num_bins); + // 2 TLB entries needed per bin + __num_bins = std::min<_DifferenceType>(__s.TLB_size / 2, __num_bins); #endif - _M_num_bins = __round_up_to_pow2(_M_num_bins); + __num_bins = __round_up_to_pow2(__num_bins); #if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1 - } + } #endif - int _M_num_bits = __rd_log2(_M_num_bins); + int __num_bits = __rd_log2(__num_bins); - if (_M_num_bins > 1) - { - _ValueType* __target = static_cast<_ValueType*>( - ::operator new(sizeof(_ValueType) * __n)); - _BinIndex* __oracles = new _BinIndex[__n]; - _DifferenceType* __dist0 = new _DifferenceType[_M_num_bins + 1], - * __dist1 = new _DifferenceType[_M_num_bins + 1]; - - for (int __b = 0; __b < _M_num_bins + 1; ++__b) - __dist0[__b] = 0; - - _RandomNumber bitrng(__rng(0xFFFFFFFF)); - - for (_DifferenceType __i = 0; __i < __n; ++__i) - { - _BinIndex __oracle = __random_number_pow2(_M_num_bits, bitrng); - __oracles[__i] = __oracle; - - // To allow prefix (partial) sum. - ++(__dist0[__oracle + 1]); - } - - // Sum up bins. - __gnu_sequential:: - partial_sum(__dist0, __dist0 + _M_num_bins + 1, __dist0); - - for (int __b = 0; __b < _M_num_bins + 1; ++__b) - __dist1[__b] = __dist0[__b]; - - // Distribute according to oracles. - for (_DifferenceType __i = 0; __i < __n; ++__i) - ::new(&(__target[(__dist0[__oracles[__i]])++])) - _ValueType(*(__begin + __i)); - - for (int __b = 0; __b < _M_num_bins; ++__b) - { - __sequential_random_shuffle(__target + __dist1[__b], - __target + __dist1[__b + 1], - __rng); - } - - // Copy elements back. - std::copy(__target, __target + __n, __begin); - - delete[] __dist0; - delete[] __dist1; - delete[] __oracles; - ::operator delete(__target); - } - else - __gnu_sequential::random_shuffle(__begin, __end, __rng); - } - -/** @brief Parallel random public call. - * @param __begin Begin iterator of sequence. - * @param __end End iterator of sequence. - * @param __rng Random number generator to use. - */ -template<typename _RAIter, typename _RandomNumberGenerator> - inline void - __parallel_random_shuffle(_RAIter __begin, - _RAIter __end, - _RandomNumberGenerator __rng = _RandomNumber()) - { - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; - _DifferenceType __n = __end - __begin; - __parallel_random_shuffle_drs( - __begin, __end, __n, __get_max_threads(), __rng) ; - } + if (__num_bins > 1) + { + _ValueType* __target = + static_cast<_ValueType*>(::operator new(sizeof(_ValueType) * __n)); + _BinIndex* __oracles = new _BinIndex[__n]; + _DifferenceType* __dist0 = new _DifferenceType[__num_bins + 1], + * __dist1 = new _DifferenceType[__num_bins + 1]; + + for (int __b = 0; __b < __num_bins + 1; ++__b) + __dist0[__b] = 0; + + _RandomNumber __bitrng(__rng(0xFFFFFFFF)); + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + _BinIndex __oracle = __random_number_pow2(__num_bits, __bitrng); + __oracles[__i] = __oracle; + + // To allow prefix (partial) sum. + ++(__dist0[__oracle + 1]); + } + + // Sum up bins. + __gnu_sequential::partial_sum(__dist0, __dist0 + __num_bins + 1, + __dist0); + + for (int __b = 0; __b < __num_bins + 1; ++__b) + __dist1[__b] = __dist0[__b]; + + // Distribute according to oracles. + for (_DifferenceType __i = 0; __i < __n; ++__i) + ::new(&(__target[(__dist0[__oracles[__i]])++])) + _ValueType(*(__begin + __i)); + + for (int __b = 0; __b < __num_bins; ++__b) + __sequential_random_shuffle(__target + __dist1[__b], + __target + __dist1[__b + 1], __rng); + + // Copy elements back. + std::copy(__target, __target + __n, __begin); + + delete[] __dist0; + delete[] __dist1; + delete[] __oracles; + ::operator delete(__target); + } + else + __gnu_sequential::random_shuffle(__begin, __end, __rng); + } + + /** @brief Parallel random public call. + * @param __begin Begin iterator of sequence. + * @param __end End iterator of sequence. + * @param __rng Random number generator to use. + */ + template<typename _RAIter, typename _RandomNumberGenerator> + inline void + __parallel_random_shuffle(_RAIter __begin, _RAIter __end, + _RandomNumberGenerator __rng = _RandomNumber()) + { + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + _DifferenceType __n = __end - __begin; + __parallel_random_shuffle_drs(__begin, __end, __n, + __get_max_threads(), __rng); + } } #endif /* _GLIBCXX_PARALLEL_RANDOM_SHUFFLE_H */ diff --git a/libstdc++-v3/include/parallel/search.h b/libstdc++-v3/include/parallel/search.h index 1fc8ceaa5c8..9709925618d 100644 --- a/libstdc++-v3/include/parallel/search.h +++ b/libstdc++-v3/include/parallel/search.h @@ -38,7 +38,6 @@ #include <parallel/parallel.h> #include <parallel/equally_split.h> - namespace __gnu_parallel { /** @@ -47,24 +46,24 @@ namespace __gnu_parallel * @param __length Length of sequence to search for. * @param __advances Returned __offsets. */ -template<typename _RAIter, typename _DifferenceTp> - void - __calc_borders(_RAIter __elements, _DifferenceTp __length, - _DifferenceTp* __off) - { - typedef _DifferenceTp _DifferenceType; - - __off[0] = -1; - if (__length > 1) - __off[1] = 0; - _DifferenceType __k = 0; - for (_DifferenceType __j = 2; __j <= __length; __j++) - { - while ((__k >= 0) && !(__elements[__k] == __elements[__j-1])) - __k = __off[__k]; - __off[__j] = ++__k; - } - } + template<typename _RAIter, typename _DifferenceTp> + void + __calc_borders(_RAIter __elements, _DifferenceTp __length, + _DifferenceTp* __off) + { + typedef _DifferenceTp _DifferenceType; + + __off[0] = -1; + if (__length > 1) + __off[1] = 0; + _DifferenceType __k = 0; + for (_DifferenceType __j = 2; __j <= __length; __j++) + { + while ((__k >= 0) && !(__elements[__k] == __elements[__j-1])) + __k = __off[__k]; + __off[__j] = ++__k; + } + } // Generic parallel find algorithm (requires random access iterator). @@ -75,100 +74,99 @@ template<typename _RAIter, typename _DifferenceTp> * @param __end2 End iterator of second sequence. * @param __pred Find predicate. * @return Place of finding in first sequences. */ -template<typename __RAIter1, - typename __RAIter2, - typename _Pred> - __RAIter1 - __search_template(__RAIter1 __begin1, __RAIter1 __end1, - __RAIter2 __begin2, __RAIter2 __end2, - _Pred __pred) - { - typedef std::iterator_traits<__RAIter1> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; + template<typename __RAIter1, + typename __RAIter2, + typename _Pred> + __RAIter1 + __search_template(__RAIter1 __begin1, __RAIter1 __end1, + __RAIter2 __begin2, __RAIter2 __end2, + _Pred __pred) + { + typedef std::iterator_traits<__RAIter1> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; - _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2)); + _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2)); - _DifferenceType __pattern_length = __end2 - __begin2; + _DifferenceType __pattern_length = __end2 - __begin2; - // Pattern too short. - if(__pattern_length <= 0) - return __end1; + // Pattern too short. + if(__pattern_length <= 0) + return __end1; - // Last point to start search. - _DifferenceType __input_length = (__end1 - __begin1) - __pattern_length; + // Last point to start search. + _DifferenceType __input_length = (__end1 - __begin1) - __pattern_length; - // Where is first occurrence of pattern? defaults to end. - _DifferenceType __result = (__end1 - __begin1); - _DifferenceType *__splitters; + // Where is first occurrence of pattern? defaults to end. + _DifferenceType __result = (__end1 - __begin1); + _DifferenceType *__splitters; - // Pattern too long. - if (__input_length < 0) - return __end1; + // Pattern too long. + if (__input_length < 0) + return __end1; - omp_lock_t __result_lock; - omp_init_lock(&__result_lock); + omp_lock_t __result_lock; + omp_init_lock(&__result_lock); - _ThreadIndex __num_threads = - std::max<_DifferenceType>(1, - std::min<_DifferenceType>(__input_length, __get_max_threads())); + _ThreadIndex __num_threads = std::max<_DifferenceType> + (1, std::min<_DifferenceType>(__input_length, + __get_max_threads())); - _DifferenceType __advances[__pattern_length]; - __calc_borders(__begin2, __pattern_length, __advances); + _DifferenceType __advances[__pattern_length]; + __calc_borders(__begin2, __pattern_length, __advances); -# pragma omp parallel num_threads(__num_threads) +# pragma omp parallel num_threads(__num_threads) { # pragma omp single - { - __num_threads = omp_get_num_threads(); - __splitters = new _DifferenceType[__num_threads + 1]; - equally_split(__input_length, __num_threads, __splitters); - } - - _ThreadIndex __iam = omp_get_thread_num(); - - _DifferenceType __start = __splitters[__iam], - __stop = __splitters[__iam + 1]; - - _DifferenceType __pos_in_pattern = 0; - bool __found_pattern = false; - - while (__start <= __stop && !__found_pattern) - { - // Get new value of result. - #pragma omp flush(__result) - // No chance for this thread to find first occurrence. - if (__result < __start) - break; - while (__pred(__begin1[__start + __pos_in_pattern], - __begin2[__pos_in_pattern])) - { - ++__pos_in_pattern; - if (__pos_in_pattern == __pattern_length) - { - // Found new candidate for result. - omp_set_lock(&__result_lock); - __result = std::min(__result, __start); - omp_unset_lock(&__result_lock); - - __found_pattern = true; - break; - } - } - // Make safe jump. - __start += (__pos_in_pattern - __advances[__pos_in_pattern]); - __pos_in_pattern = - (__advances[__pos_in_pattern] < 0) ? - 0 : __advances[__pos_in_pattern]; - } + { + __num_threads = omp_get_num_threads(); + __splitters = new _DifferenceType[__num_threads + 1]; + equally_split(__input_length, __num_threads, __splitters); + } + + _ThreadIndex __iam = omp_get_thread_num(); + + _DifferenceType __start = __splitters[__iam], + __stop = __splitters[__iam + 1]; + + _DifferenceType __pos_in_pattern = 0; + bool __found_pattern = false; + + while (__start <= __stop && !__found_pattern) + { + // Get new value of result. +#pragma omp flush(__result) + // No chance for this thread to find first occurrence. + if (__result < __start) + break; + while (__pred(__begin1[__start + __pos_in_pattern], + __begin2[__pos_in_pattern])) + { + ++__pos_in_pattern; + if (__pos_in_pattern == __pattern_length) + { + // Found new candidate for result. + omp_set_lock(&__result_lock); + __result = std::min(__result, __start); + omp_unset_lock(&__result_lock); + + __found_pattern = true; + break; + } + } + // Make safe jump. + __start += (__pos_in_pattern - __advances[__pos_in_pattern]); + __pos_in_pattern = (__advances[__pos_in_pattern] < 0 + ? 0 : __advances[__pos_in_pattern]); + } } //parallel - omp_destroy_lock(&__result_lock); - - delete[] __splitters; + omp_destroy_lock(&__result_lock); - // Return iterator on found element. - return (__begin1 + __result); - } + delete[] __splitters; + + // Return iterator on found element. + return (__begin1 + __result); + } } // end namespace #endif /* _GLIBCXX_PARALLEL_SEARCH_H */ diff --git a/libstdc++-v3/include/parallel/set_operations.h b/libstdc++-v3/include/parallel/set_operations.h index ac669c55d5d..6dd63c9b128 100644 --- a/libstdc++-v3/include/parallel/set_operations.h +++ b/libstdc++-v3/include/parallel/set_operations.h @@ -41,490 +41,489 @@ 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) + 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 { - do + while (__a != __b && __c != __d) { - *__r++ = *__b.first++; + if (_M_comp(*__a, *__c)) + { + *__r = *__a; + ++__a; + ++__r; + } + else if (_M_comp(*__c, *__a)) + { + *__r = *__c; + ++__c; + ++__r; + } + else + { + ++__a; + ++__c; + } } - while (__b.first != __e.first); + return std::copy(__c, __d, std::copy(__a, __b, __r)); } - else + + _DifferenceType + __count(_IIter __a, _IIter __b, _IIter __c, _IIter d) const { - while (__b.second != __e.second) - *__r++ = *__b.second++; + _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); } - 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; + _OutputIterator + __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const + { return std::copy(__c, d, __out); } - symmetric_difference_func(_Compare __comp) : _M_comp(__comp) {} + _OutputIterator + __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const + { return std::copy(__a, __b, __out); } + }; - _Compare _M_comp; - _OutputIterator - _M_invoke(_IIter __a, _IIter __b, - _IIter __c, _IIter d, - _OutputIterator __r) const + template<typename _IIter, + typename _OutputIterator, + typename _Compare> + struct __difference_func { - 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)); - } + typedef std::iterator_traits<_IIter> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef typename std::pair<_IIter, _IIter> _IteratorPair; - _DifferenceType - __count(_IIter __a, _IIter __b, - _IIter __c, _IIter d) const - { - _DifferenceType __counter = 0; + __difference_func(_Compare __comp) : _M_comp(__comp) {} - while (__a != __b && __c != d) - { - if (_M_comp(*__a, *__c)) - { - ++__a; - ++__counter; - } - else if (_M_comp(*__c, *__a)) - { - ++__c; - ++__counter; - } - else - { - ++__a; - ++__c; - } - } + _Compare _M_comp; - return __counter + (__b - __a) + (d - __c); - } + _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); + } - _OutputIterator - __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const - { return std::copy(__c, d, __out); } + _DifferenceType + __count(_IIter __a, _IIter __b, + _IIter __c, _IIter d) const + { + _DifferenceType __counter = 0; - _OutputIterator - __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const - { return std::copy(__a, __b, __out); } - }; + 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); + } -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; + _OutputIterator + __first_empty(_IIter, _IIter, _OutputIterator __out) const + { return __out; } - __difference_func(_Compare __comp) : _M_comp(__comp) {} + _OutputIterator + __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const + { return std::copy(__a, __b, __out); } + }; - _Compare _M_comp; - _OutputIterator - _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter d, - _OutputIterator __r) const + template<typename _IIter, + typename _OutputIterator, + typename _Compare> + struct __intersection_func { - 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); - } + typedef std::iterator_traits<_IIter> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef typename std::pair<_IIter, _IIter> _IteratorPair; - _DifferenceType - __count(_IIter __a, _IIter __b, - _IIter __c, _IIter d) const - { - _DifferenceType __counter = 0; + __intersection_func(_Compare __comp) : _M_comp(__comp) {} - while (__a != __b && __c != d) - { - if (_M_comp(*__a, *__c)) - { - ++__a; - ++__counter; - } - else if (_M_comp(*__c, *__a)) - { ++__c; } - else - { ++__a; ++__c; } - } + _Compare _M_comp; - return __counter + (__b - __a); - } + _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; + } + } - inline _OutputIterator - __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const - { return __out; } + return __r; + } - inline _OutputIterator - __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const - { return std::copy(__a, __b, __out); } - }; + _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; + } + } -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; + return __counter; + } - __intersection_func(_Compare __comp) : _M_comp(__comp) {} + _OutputIterator + __first_empty(_IIter, _IIter, _OutputIterator __out) const + { return __out; } - _Compare _M_comp; + _OutputIterator + __second_empty(_IIter, _IIter, _OutputIterator __out) const + { return __out; } + }; - _OutputIterator - _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter d, - _OutputIterator __r) const + template<class _IIter, class _OutputIterator, class _Compare> + struct __union_func { - while (__a != __b && __c != d) - { - if (_M_comp(*__a, *__c)) - { ++__a; } - else if (_M_comp(*__c, *__a)) - { ++__c; } - else - { - *__r = *__a; - ++__a; - ++__c; - ++__r; - } - } + typedef typename std::iterator_traits<_IIter>::difference_type + _DifferenceType; - return __r; - } + __union_func(_Compare __comp) : _M_comp(__comp) {} - _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; - } - } + _Compare _M_comp; - return __counter; - } + _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)); + } - inline _OutputIterator - __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const - { return __out; } + _DifferenceType + __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const + { + _DifferenceType __counter = 0; - inline _OutputIterator - __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const - { return __out; } - }; + while (__a != __b && __c != __d) + { + if (_M_comp(*__a, *__c)) + { ++__a; } + else if (_M_comp(*__c, *__a)) + { ++__c; } + else + { + ++__a; + ++__c; + } + ++__counter; + } -template<class _IIter, class _OutputIterator, class _Compare> - struct __union_func - { - typedef typename std::iterator_traits<_IIter>::difference_type - _DifferenceType; + __counter += (__b - __a); + __counter += (__d - __c); + return __counter; + } - __union_func(_Compare __comp) : _M_comp(__comp) {} + _OutputIterator + __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const + { return std::copy(__c, __d, __out); } - _Compare _M_comp; + _OutputIterator + __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const + { return std::copy(__a, __b, __out); } + }; + template<typename _IIter, + typename _OutputIterator, + typename Operation> _OutputIterator - _M_invoke(_IIter __a, const _IIter __b, _IIter __c, - const _IIter d, _OutputIterator __r) const + __parallel_set_operation(_IIter __begin1, _IIter __end1, + _IIter __begin2, _IIter __end2, + _OutputIterator __result, Operation __op) { - 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)); - } + _GLIBCXX_CALL((__end1 - __begin1) + (__end2 - __begin2)) - _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; - } + typedef std::iterator_traits<_IIter> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + typedef typename std::pair<_IIter, _IIter> _IteratorPair; - __counter += (__b - __a); - __counter += (d - __c); - return __counter; - } + if (__begin1 == __end1) + return __op.__first_empty(__begin2, __end2, __result); - inline _OutputIterator - __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const - { return std::copy(__c, d, __out); } + if (__begin2 == __end2) + return __op.__second_empty(__begin1, __end1, __result); - inline _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) + 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 ]); + { + __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 - // Make sure all threads have their block_begin result written out. + _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 - _IteratorPair __block_begin = __block_begins[ __iam ]; + _OutputIterator __r = __result; - // 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); - } + if (__iam == 0) + { + // Do the last block. + for (int __i = 0; __i < __num_threads; ++__i) + __r += __lengths[__i]; - // Make sure everyone wrote their lengths. -# pragma omp barrier + __block_begin = __block_begins[__num_threads]; - _OutputIterator __r = __result; + // Return the result iterator of the last block. + __return_value = + __op._M_invoke(__block_begin.first, __end1, + __block_begin.second, __end2, __r); - if (__iam == 0) - { - // Do the last block. - for (int __i = 0; __i < __num_threads; ++__i) - __r += __lengths[__i]; + } + else + { + for (int __i = 0; __i < __iam; ++__i) + __r += __lengths[ __i ]; - __block_begin = __block_begins[__num_threads]; + // Reset begins for copy pass. + __op._M_invoke(__block_begin.first, __block_end.first, + __block_begin.second, __block_end.second, __r); + } + } + return __return_value; + } - // Return the result iterator of the last block. - return_value = __op._M_invoke( - __block_begin.first, __end1, __block_begin.second, __end2, __r); + 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)); + } - } - else - { - for (int __i = 0; __i < __iam; ++__i) - __r += __lengths[ __i ]; + 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)); + } - // 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 _M_comp) - { - return __parallel_set_operation(__begin1, __end1, __begin2, __end2, - __result, __union_func< _IIter, _OutputIterator, _Compare>(_M_comp)); - } - -template<typename _IIter, - typename _OutputIterator, - typename _Compare> - inline _OutputIterator - __parallel_set_intersection(_IIter __begin1, _IIter __end1, + template<typename _IIter, + typename _OutputIterator, + typename _Compare> + inline _OutputIterator + __parallel_set_difference(_IIter __begin1, _IIter __end1, _IIter __begin2, _IIter __end2, - _OutputIterator __result, _Compare _M_comp) - { - return __parallel_set_operation( - __begin1, __end1, __begin2, __end2, __result, - __intersection_func<_IIter, _OutputIterator, _Compare>(_M_comp)); - } - -template<typename _IIter, - typename _OutputIterator, - typename _Compare> - inline _OutputIterator - __parallel_set_difference(_IIter __begin1, _IIter __end1, - _IIter __begin2, _IIter __end2, - _OutputIterator __result, _Compare _M_comp) - { - return __parallel_set_operation( - __begin1, __end1, __begin2, __end2, __result, - __difference_func<_IIter, _OutputIterator, _Compare>(_M_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 _M_comp) - { - return __parallel_set_operation( - __begin1, __end1, __begin2, __end2, __result, - symmetric_difference_func<_IIter, _OutputIterator, _Compare> - (_M_comp)); - } + _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 */ diff --git a/libstdc++-v3/include/parallel/sort.h b/libstdc++-v3/include/parallel/sort.h index 2d38cad4d96..f1a163c63b6 100644 --- a/libstdc++-v3/include/parallel/sort.h +++ b/libstdc++-v3/include/parallel/sort.h @@ -54,12 +54,12 @@ namespace __gnu_parallel { - //prototype + //prototype template<bool __stable, typename _RAIter, typename _Compare, typename _Parallelism> - void - __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, _Parallelism __parallelism); + void + __parallel_sort(_RAIter __begin, _RAIter __end, + _Compare __comp, _Parallelism __parallelism); /** * @brief Choose multiway mergesort, splitting variant at run-time, @@ -70,19 +70,19 @@ namespace __gnu_parallel * @callgraph */ template<bool __stable, typename _RAIter, typename _Compare> - inline void - __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, multiway_mergesort_tag __parallelism) - { - _GLIBCXX_CALL(__end - __begin) + inline void + __parallel_sort(_RAIter __begin, _RAIter __end, + _Compare __comp, multiway_mergesort_tag __parallelism) + { + _GLIBCXX_CALL(__end - __begin) - if(_Settings::get().sort_splitting == EXACT) - parallel_sort_mwms<__stable, true> - (__begin, __end, __comp, __parallelism.__get_num_threads()); - else - parallel_sort_mwms<__stable, false> - (__begin, __end, __comp, __parallelism.__get_num_threads()); - } + if(_Settings::get().sort_splitting == EXACT) + parallel_sort_mwms<__stable, true> + (__begin, __end, __comp, __parallelism.__get_num_threads()); + else + parallel_sort_mwms<__stable, false> + (__begin, __end, __comp, __parallelism.__get_num_threads()); + } /** * @brief Choose multiway mergesort with exact splitting, @@ -93,15 +93,16 @@ namespace __gnu_parallel * @callgraph */ template<bool __stable, typename _RAIter, typename _Compare> - inline void - __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, multiway_mergesort_exact_tag __parallelism) - { - _GLIBCXX_CALL(__end - __begin) + inline void + __parallel_sort(_RAIter __begin, _RAIter __end, + _Compare __comp, + multiway_mergesort_exact_tag __parallelism) + { + _GLIBCXX_CALL(__end - __begin) parallel_sort_mwms<__stable, true> (__begin, __end, __comp, __parallelism.__get_num_threads()); - } + } /** * @brief Choose multiway mergesort with splitting by sampling, @@ -112,15 +113,16 @@ namespace __gnu_parallel * @callgraph */ template<bool __stable, typename _RAIter, typename _Compare> - inline void - __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, multiway_mergesort_sampling_tag __parallelism) - { - _GLIBCXX_CALL(__end - __begin) + inline void + __parallel_sort(_RAIter __begin, _RAIter __end, + _Compare __comp, + multiway_mergesort_sampling_tag __parallelism) + { + _GLIBCXX_CALL(__end - __begin) - parallel_sort_mwms<__stable, false> + parallel_sort_mwms<__stable, false> (__begin, __end, __comp, __parallelism.__get_num_threads()); - } + } /** * @brief Choose quicksort for parallel sorting. @@ -130,17 +132,17 @@ namespace __gnu_parallel * @callgraph */ template<bool __stable, typename _RAIter, typename _Compare> - inline void - __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, quicksort_tag __parallelism) - { - _GLIBCXX_CALL(__end - __begin) + inline void + __parallel_sort(_RAIter __begin, _RAIter __end, + _Compare __comp, quicksort_tag __parallelism) + { + _GLIBCXX_CALL(__end - __begin) - _GLIBCXX_PARALLEL_ASSERT(__stable == false); + _GLIBCXX_PARALLEL_ASSERT(__stable == false); - __parallel_sort_qs(__begin, __end, __comp, - __parallelism.__get_num_threads()); - } + __parallel_sort_qs(__begin, __end, __comp, + __parallelism.__get_num_threads()); + } /** * @brief Choose balanced quicksort for parallel sorting. @@ -150,19 +152,18 @@ namespace __gnu_parallel * @param __stable Sort __stable. * @callgraph */ - template<bool __stable, typename _RAIter, typename _Compare> - inline void - __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, balanced_quicksort_tag __parallelism) - { - _GLIBCXX_CALL(__end - __begin) - - _GLIBCXX_PARALLEL_ASSERT(__stable == false); + template<bool __stable, typename _RAIter, typename _Compare> + inline void + __parallel_sort(_RAIter __begin, _RAIter __end, + _Compare __comp, balanced_quicksort_tag __parallelism) + { + _GLIBCXX_CALL(__end - __begin) - __parallel_sort_qsb(__begin, __end, __comp, - __parallelism.__get_num_threads()); - } + _GLIBCXX_PARALLEL_ASSERT(__stable == false); + __parallel_sort_qsb(__begin, __end, __comp, + __parallelism.__get_num_threads()); + } /** * @brief Choose multiway mergesort with exact splitting, @@ -173,17 +174,16 @@ namespace __gnu_parallel * @callgraph */ template<bool __stable, typename _RAIter, typename _Compare> - inline void - __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, default_parallel_tag __parallelism) - { - _GLIBCXX_CALL(__end - __begin) - - __parallel_sort<__stable> - (__begin, __end, __comp, - multiway_mergesort_exact_tag(__parallelism.__get_num_threads())); - } + inline void + __parallel_sort(_RAIter __begin, _RAIter __end, + _Compare __comp, default_parallel_tag __parallelism) + { + _GLIBCXX_CALL(__end - __begin) + __parallel_sort<__stable> + (__begin, __end, __comp, + multiway_mergesort_exact_tag(__parallelism.__get_num_threads())); + } /** * @brief Choose a parallel sorting algorithm. @@ -196,7 +196,7 @@ namespace __gnu_parallel template<bool __stable, typename _RAIter, typename _Compare> inline void __parallel_sort(_RAIter __begin, _RAIter __end, - _Compare __comp, parallel_tag __parallelism) + _Compare __comp, parallel_tag __parallelism) { _GLIBCXX_CALL(__end - __begin) typedef std::iterator_traits<_RAIter> _TraitsType; diff --git a/libstdc++-v3/include/parallel/tags.h b/libstdc++-v3/include/parallel/tags.h index 43561d28d5c..bc47b2699b4 100644 --- a/libstdc++-v3/include/parallel/tags.h +++ b/libstdc++-v3/include/parallel/tags.h @@ -51,20 +51,16 @@ namespace __gnu_parallel public: /** @brief Default constructor. Use default number of threads. */ parallel_tag() - { - this->_M_num_threads = 0; - } + { _M_num_threads = 0; } /** @brief Default constructor. Recommend number of threads to use. * @param __num_threads Desired number of threads. */ parallel_tag(_ThreadIndex __num_threads) - { - this->_M_num_threads = __num_threads; - } + { _M_num_threads = __num_threads; } /** @brief Find out desired number of threads. * @return Desired number of threads. */ - inline _ThreadIndex __get_num_threads() + _ThreadIndex __get_num_threads() { if(_M_num_threads == 0) return omp_get_max_threads(); @@ -74,19 +70,17 @@ namespace __gnu_parallel /** @brief Set the desired number of threads. * @param __num_threads Desired number of threads. */ - inline void set_num_threads(_ThreadIndex __num_threads) - { - this->_M_num_threads = __num_threads; - } + void set_num_threads(_ThreadIndex __num_threads) + { _M_num_threads = __num_threads; } }; /** @brief Recommends parallel execution using the default parallel algorithm. */ struct default_parallel_tag : public parallel_tag { - default_parallel_tag() { } - default_parallel_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + default_parallel_tag() { } + default_parallel_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; /** @brief Recommends parallel execution using dynamic @@ -114,18 +108,18 @@ namespace __gnu_parallel * with exact splitting, at compile time. */ struct exact_tag : public parallel_tag { - exact_tag() { } - exact_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + exact_tag() { } + exact_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; /** @brief Forces parallel merging * with exact splitting, at compile time. */ struct sampling_tag : public parallel_tag { - sampling_tag() { } - sampling_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + sampling_tag() { } + sampling_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; @@ -133,45 +127,45 @@ namespace __gnu_parallel * at compile time. */ struct multiway_mergesort_tag : public parallel_tag { - multiway_mergesort_tag() { } - multiway_mergesort_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + multiway_mergesort_tag() { } + multiway_mergesort_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; /** @brief Forces parallel sorting using multiway mergesort * with exact splitting at compile time. */ struct multiway_mergesort_exact_tag : public parallel_tag { - multiway_mergesort_exact_tag() { } - multiway_mergesort_exact_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + multiway_mergesort_exact_tag() { } + multiway_mergesort_exact_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; /** @brief Forces parallel sorting using multiway mergesort * with splitting by sampling at compile time. */ struct multiway_mergesort_sampling_tag : public parallel_tag { - multiway_mergesort_sampling_tag() { } - multiway_mergesort_sampling_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + multiway_mergesort_sampling_tag() { } + multiway_mergesort_sampling_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; /** @brief Forces parallel sorting using unbalanced quicksort * at compile time. */ struct quicksort_tag : public parallel_tag { - quicksort_tag() { } - quicksort_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + quicksort_tag() { } + quicksort_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; /** @brief Forces parallel sorting using balanced quicksort * at compile time. */ struct balanced_quicksort_tag : public parallel_tag { - balanced_quicksort_tag() { } - balanced_quicksort_tag(_ThreadIndex __num_threads) - : parallel_tag(__num_threads) { } + balanced_quicksort_tag() { } + balanced_quicksort_tag(_ThreadIndex __num_threads) + : parallel_tag(__num_threads) { } }; diff --git a/libstdc++-v3/include/parallel/unique_copy.h b/libstdc++-v3/include/parallel/unique_copy.h index 327870e7d86..1ae5a12316d 100644 --- a/libstdc++-v3/include/parallel/unique_copy.h +++ b/libstdc++-v3/include/parallel/unique_copy.h @@ -37,155 +37,160 @@ namespace __gnu_parallel { - -/** @brief Parallel std::unique_copy(), w/__o explicit equality predicate. - * @param __first Begin iterator of input sequence. - * @param __last End iterator of input sequence. - * @param __result Begin iterator of result __sequence. - * @param __binary_pred Equality predicate. - * @return End iterator of result __sequence. */ -template<typename _IIter, - class _OutputIterator, - class _BinaryPredicate> - _OutputIterator - __parallel_unique_copy(_IIter __first, _IIter __last, - _OutputIterator __result, _BinaryPredicate __binary_pred) - { - _GLIBCXX_CALL(__last - __first) - - typedef std::iterator_traits<_IIter> _TraitsType; - typedef typename _TraitsType::value_type _ValueType; - typedef typename _TraitsType::difference_type _DifferenceType; - - _DifferenceType size = __last - __first; - - if (size == 0) - return __result; - - // Let the first thread process two parts. - _DifferenceType *__counter; - _DifferenceType *__borders; - - _ThreadIndex __num_threads = __get_max_threads(); - // First part contains at least one element. -# pragma omp parallel num_threads(__num_threads) + /** @brief Parallel std::unique_copy(), w/__o explicit equality predicate. + * @param __first Begin iterator of input sequence. + * @param __last End iterator of input sequence. + * @param __result Begin iterator of result __sequence. + * @param __binary_pred Equality predicate. + * @return End iterator of result __sequence. */ + template<typename _IIter, + class _OutputIterator, + class _BinaryPredicate> + _OutputIterator + __parallel_unique_copy(_IIter __first, _IIter __last, + _OutputIterator __result, + _BinaryPredicate __binary_pred) + { + _GLIBCXX_CALL(__last - __first) + + typedef std::iterator_traits<_IIter> _TraitsType; + typedef typename _TraitsType::value_type _ValueType; + typedef typename _TraitsType::difference_type _DifferenceType; + + _DifferenceType __size = __last - __first; + + if (__size == 0) + return __result; + + // Let the first thread process two parts. + _DifferenceType *__counter; + _DifferenceType *__borders; + + _ThreadIndex __num_threads = __get_max_threads(); + // First part contains at least one element. +# 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); + __counter = new _DifferenceType[__num_threads + 1]; + } + + _ThreadIndex __iam = omp_get_thread_num(); + + _DifferenceType __begin, __end; + + // Check for length without duplicates + // Needed for position in output + _DifferenceType __i = 0; + _OutputIterator __out = __result; + + if (__iam == 0) { - __num_threads = omp_get_num_threads(); - __borders = new _DifferenceType[__num_threads + 2]; - equally_split(size, __num_threads + 1, __borders); - __counter = new _DifferenceType[__num_threads + 1]; + __begin = __borders[0] + 1; // == 1 + __end = __borders[__iam + 1]; + + ++__i; + *__out++ = *__first; + + for (_IIter __iter = __first + __begin; __iter < __first + __end; + ++__iter) + { + if (!__binary_pred(*__iter, *(__iter - 1))) + { + ++__i; + *__out++ = *__iter; + } + } } + else + { + __begin = __borders[__iam]; //one part + __end = __borders[__iam + 1]; - _ThreadIndex __iam = omp_get_thread_num(); + for (_IIter __iter = __first + __begin; __iter < __first + __end; + ++__iter) + { + if (!__binary_pred(*__iter, *(__iter - 1))) + ++__i; + } + } + __counter[__iam] = __i; - _DifferenceType __begin, __end; + // Last part still untouched. + _DifferenceType __begin_output; - // Check for length without duplicates - // Needed for position in output - _DifferenceType __i = 0; - _OutputIterator __out = __result; +# pragma omp barrier - if (__iam == 0) - { - __begin = __borders[0] + 1; // == 1 - __end = __borders[__iam + 1]; + // Store result in output on calculated positions. + __begin_output = 0; - ++__i; - *__out++ = *__first; + if (__iam == 0) + { + for (int __t = 0; __t < __num_threads; ++__t) + __begin_output += __counter[__t]; - for (_IIter iter = __first + __begin; iter < __first + __end; ++iter) - { - if (!__binary_pred(*iter, *(iter-1))) - { - ++__i; - *__out++ = *iter; - } - } - } - else - { - __begin = __borders[__iam]; //one part - __end = __borders[__iam + 1]; - - for (_IIter iter = __first + __begin; iter < __first + __end; ++iter) - { - if (!__binary_pred(*iter, *(iter - 1))) - ++__i; - } - } - __counter[__iam] = __i; - - // Last part still untouched. - _DifferenceType __begin_output; - -# pragma omp barrier - - // Store result in output on calculated positions. - __begin_output = 0; - - if (__iam == 0) - { - for (int __t = 0; __t < __num_threads; ++__t) - __begin_output += __counter[__t]; - - __i = 0; - - _OutputIterator __iter_out = __result + __begin_output; - - __begin = __borders[__num_threads]; - __end = size; - - for (_IIter iter = __first + __begin; iter < __first + __end; ++iter) - { - if (iter == __first || !__binary_pred(*iter, *(iter - 1))) - { - ++__i; - *__iter_out++ = *iter; - } - } - - __counter[__num_threads] = __i; - } - else - { - for (int __t = 0; __t < __iam; __t++) - __begin_output += __counter[__t]; - - _OutputIterator __iter_out = __result + __begin_output; - for (_IIter iter = __first + __begin; iter < __first + __end; ++iter) - { - if (!__binary_pred(*iter, *(iter-1))) - *__iter_out++ = *iter; - } - } + __i = 0; + + _OutputIterator __iter_out = __result + __begin_output; + + __begin = __borders[__num_threads]; + __end = __size; + + for (_IIter __iter = __first + __begin; __iter < __first + __end; + ++__iter) + { + if (__iter == __first + || !__binary_pred(*__iter, *(__iter - 1))) + { + ++__i; + *__iter_out++ = *__iter; + } + } + + __counter[__num_threads] = __i; + } + else + { + for (int __t = 0; __t < __iam; __t++) + __begin_output += __counter[__t]; + + _OutputIterator __iter_out = __result + __begin_output; + for (_IIter __iter = __first + __begin; __iter < __first + __end; + ++__iter) + { + if (!__binary_pred(*__iter, *(__iter - 1))) + *__iter_out++ = *__iter; + } + } + } + + _DifferenceType __end_output = 0; + for (int __t = 0; __t < __num_threads + 1; __t++) + __end_output += __counter[__t]; + + delete[] __borders; + + return __result + __end_output; } - _DifferenceType __end_output = 0; - for (int __t = 0; __t < __num_threads + 1; __t++) - __end_output += __counter[__t]; - - delete[] __borders; - - return __result + __end_output; - } - -/** @brief Parallel std::unique_copy(), without explicit equality predicate - * @param __first Begin iterator of input sequence. - * @param __last End iterator of input sequence. - * @param __result Begin iterator of result __sequence. - * @return End iterator of result __sequence. */ -template<typename _IIter, class _OutputIterator> - inline _OutputIterator - __parallel_unique_copy(_IIter __first, _IIter __last, - _OutputIterator __result) - { - typedef typename std::iterator_traits<_IIter>::value_type - _ValueType; - return __parallel_unique_copy(__first, __last, __result, - std::equal_to<_ValueType>()); - } + /** @brief Parallel std::unique_copy(), without explicit equality predicate + * @param __first Begin iterator of input sequence. + * @param __last End iterator of input sequence. + * @param __result Begin iterator of result __sequence. + * @return End iterator of result __sequence. */ + template<typename _IIter, class _OutputIterator> + inline _OutputIterator + __parallel_unique_copy(_IIter __first, _IIter __last, + _OutputIterator __result) + { + typedef typename std::iterator_traits<_IIter>::value_type + _ValueType; + return __parallel_unique_copy(__first, __last, __result, + std::equal_to<_ValueType>()); + } }//namespace __gnu_parallel diff --git a/libstdc++-v3/include/parallel/workstealing.h b/libstdc++-v3/include/parallel/workstealing.h index 638057ca740..9e0db3a9584 100644 --- a/libstdc++-v3/include/parallel/workstealing.h +++ b/libstdc++-v3/include/parallel/workstealing.h @@ -49,261 +49,264 @@ namespace __gnu_parallel #define _GLIBCXX_JOB_VOLATILE volatile -/** @brief One __job for a certain thread. */ -template<typename _DifferenceTp> - struct _Job - { - typedef _DifferenceTp _DifferenceType; - - /** @brief First element. - * - * Changed by owning and stealing thread. By stealing thread, - * always incremented. */ - _GLIBCXX_JOB_VOLATILE _DifferenceType _M_first; - - /** @brief Last element. - * - * Changed by owning thread only. */ - _GLIBCXX_JOB_VOLATILE _DifferenceType _M_last; - - /** @brief Number of elements, i.e. @__c _M_last-_M_first+1. - * - * Changed by owning thread only. */ - _GLIBCXX_JOB_VOLATILE _DifferenceType _M_load; - }; - -/** @brief Work stealing algorithm for random access iterators. - * - * Uses O(1) additional memory. Synchronization at job lists is - * done with atomic operations. - * @param __begin Begin iterator of element sequence. - * @param __end End iterator of element sequence. - * @param __op User-supplied functor (comparator, predicate, adding - * functor, ...). - * @param __f Functor to "process" an element with __op (depends on - * desired functionality, e. g. for std::for_each(), ...). - * @param __r Functor to "add" a single __result to the already - * processed elements (depends on functionality). - * @param __base Base value for reduction. - * @param __output Pointer to position where final result is written to - * @param __bound Maximum number of elements processed (e. g. for - * std::count_n()). - * @return User-supplied functor (that may contain a part of the result). - */ -template<typename _RAIter, - typename _Op, - typename _Fu, - typename _Red, - typename _Result> - _Op - __for_each_template_random_access_workstealing( - _RAIter __begin, _RAIter __end, _Op __op, _Fu& __f, _Red __r, - _Result __base, _Result& __output, - typename std::iterator_traits<_RAIter>::difference_type __bound) - { - _GLIBCXX_CALL(__end - __begin) - - typedef std::iterator_traits<_RAIter> _TraitsType; - typedef typename _TraitsType::difference_type _DifferenceType; - - const _Settings& __s = _Settings::get(); - - _DifferenceType __chunk_size = - static_cast<_DifferenceType>(__s.workstealing_chunk_size); - - // How many jobs? - _DifferenceType __length = (__bound < 0) ? (__end - __begin) : __bound; - - // To avoid false sharing in a cache line. - const int __stride = - __s.cache_line_size * 10 / sizeof(_Job<_DifferenceType>) + 1; - - // Total number of threads currently working. - _ThreadIndex __busy = 0; - - _Job<_DifferenceType> *__job; - - omp_lock_t __output_lock; - omp_init_lock(&__output_lock); - - // Write base value to output. - __output = __base; - - // No more threads than jobs, at least one thread. - _ThreadIndex __num_threads = - __gnu_parallel::max<_ThreadIndex>(1, - __gnu_parallel::min<_DifferenceType>(__length, __get_max_threads())); - -# pragma omp parallel shared(__busy) num_threads(__num_threads) + /** @brief One __job for a certain thread. */ + template<typename _DifferenceTp> + struct _Job + { + typedef _DifferenceTp _DifferenceType; + + /** @brief First element. + * + * Changed by owning and stealing thread. By stealing thread, + * always incremented. */ + _GLIBCXX_JOB_VOLATILE _DifferenceType _M_first; + + /** @brief Last element. + * + * Changed by owning thread only. */ + _GLIBCXX_JOB_VOLATILE _DifferenceType _M_last; + + /** @brief Number of elements, i.e. @c _M_last-_M_first+1. + * + * Changed by owning thread only. */ + _GLIBCXX_JOB_VOLATILE _DifferenceType _M_load; + }; + + /** @brief Work stealing algorithm for random access iterators. + * + * Uses O(1) additional memory. Synchronization at job lists is + * done with atomic operations. + * @param __begin Begin iterator of element sequence. + * @param __end End iterator of element sequence. + * @param __op User-supplied functor (comparator, predicate, adding + * functor, ...). + * @param __f Functor to "process" an element with __op (depends on + * desired functionality, e. g. for std::for_each(), ...). + * @param __r Functor to "add" a single __result to the already + * processed elements (depends on functionality). + * @param __base Base value for reduction. + * @param __output Pointer to position where final result is written to + * @param __bound Maximum number of elements processed (e. g. for + * std::count_n()). + * @return User-supplied functor (that may contain a part of the result). + */ + template<typename _RAIter, + typename _Op, + typename _Fu, + typename _Red, + typename _Result> + _Op + __for_each_template_random_access_workstealing(_RAIter __begin, + _RAIter __end, _Op __op, + _Fu& __f, _Red __r, + _Result __base, + _Result& __output, + typename std::iterator_traits<_RAIter>::difference_type __bound) + { + _GLIBCXX_CALL(__end - __begin) + + typedef std::iterator_traits<_RAIter> _TraitsType; + typedef typename _TraitsType::difference_type _DifferenceType; + + const _Settings& __s = _Settings::get(); + + _DifferenceType __chunk_size = + static_cast<_DifferenceType>(__s.workstealing_chunk_size); + + // How many jobs? + _DifferenceType __length = (__bound < 0) ? (__end - __begin) : __bound; + + // To avoid false sharing in a cache line. + const int __stride = (__s.cache_line_size * 10 + / sizeof(_Job<_DifferenceType>) + 1); + + // Total number of threads currently working. + _ThreadIndex __busy = 0; + + _Job<_DifferenceType> *__job; + + omp_lock_t __output_lock; + omp_init_lock(&__output_lock); + + // Write base value to output. + __output = __base; + + // No more threads than jobs, at least one thread. + _ThreadIndex __num_threads = __gnu_parallel::max<_ThreadIndex> + (1, __gnu_parallel::min<_DifferenceType>(__length, + __get_max_threads())); + +# pragma omp parallel shared(__busy) num_threads(__num_threads) { - # pragma omp single - { - __num_threads = omp_get_num_threads(); + { + __num_threads = omp_get_num_threads(); - // Create job description array. - __job = new _Job<_DifferenceType>[__num_threads * __stride]; - } + // Create job description array. + __job = new _Job<_DifferenceType>[__num_threads * __stride]; + } - // Initialization phase. + // Initialization phase. - // Flags for every thread if it is doing productive work. - bool __iam_working = false; + // Flags for every thread if it is doing productive work. + bool __iam_working = false; - // Thread id. - _ThreadIndex __iam = omp_get_thread_num(); + // Thread id. + _ThreadIndex __iam = omp_get_thread_num(); - // This job. - _Job<_DifferenceType>& __my_job = __job[__iam * __stride]; + // This job. + _Job<_DifferenceType>& __my_job = __job[__iam * __stride]; - // Random number (for work stealing). - _ThreadIndex __victim; + // Random number (for work stealing). + _ThreadIndex __victim; - // Local value for reduction. - _Result __result = _Result(); + // Local value for reduction. + _Result __result = _Result(); - // Number of elements to steal in one attempt. - _DifferenceType __steal; + // Number of elements to steal in one attempt. + _DifferenceType __steal; - // Every thread has its own random number generator - // (modulo __num_threads). - _RandomNumber rand_gen(__iam, __num_threads); + // Every thread has its own random number generator + // (modulo __num_threads). + _RandomNumber __rand_gen(__iam, __num_threads); - // This thread is currently working. + // This thread is currently working. # pragma omp atomic - ++__busy; + ++__busy; - __iam_working = true; + __iam_working = true; - // How many jobs per thread? last thread gets the rest. - __my_job._M_first = - static_cast<_DifferenceType>(__iam * (__length / __num_threads)); + // How many jobs per thread? last thread gets the rest. + __my_job._M_first = static_cast<_DifferenceType> + (__iam * (__length / __num_threads)); - __my_job._M_last = (__iam == (__num_threads - 1)) ? - (__length - 1) : ((__iam + 1) * (__length / __num_threads) - 1); - __my_job._M_load = __my_job._M_last - __my_job._M_first + 1; + __my_job._M_last = (__iam == (__num_threads - 1) + ? (__length - 1) + : ((__iam + 1) * (__length / __num_threads) - 1)); + __my_job._M_load = __my_job._M_last - __my_job._M_first + 1; - // Init result with _M_first value (to have a base value for reduction) - if (__my_job._M_first <= __my_job._M_last) - { - // Cannot use volatile variable directly. - _DifferenceType __my_first = __my_job._M_first; - __result = __f(__op, __begin + __my_first); - ++__my_job._M_first; - --__my_job._M_load; - } + // Init result with _M_first value (to have a base value for reduction) + if (__my_job._M_first <= __my_job._M_last) + { + // Cannot use volatile variable directly. + _DifferenceType __my_first = __my_job._M_first; + __result = __f(__op, __begin + __my_first); + ++__my_job._M_first; + --__my_job._M_load; + } - _RAIter __current; + _RAIter __current; # pragma omp barrier - // Actual work phase - // Work on own or stolen current start - while (__busy > 0) - { - // Work until no productive thread left. + // Actual work phase + // Work on own or stolen current start + while (__busy > 0) + { + // Work until no productive thread left. # pragma omp flush(__busy) - // Thread has own work to do - while (__my_job._M_first <= __my_job._M_last) - { - // fetch-and-add call - // Reserve current job block (size __chunk_size) in my queue. - _DifferenceType __current_job = - __fetch_and_add<_DifferenceType>( - &(__my_job._M_first), __chunk_size); - - // Update _M_load, to make the three values consistent, - // _M_first might have been changed in the meantime - __my_job._M_load = __my_job._M_last - __my_job._M_first + 1; - for (_DifferenceType __job_counter = 0; - __job_counter < __chunk_size - && __current_job <= __my_job._M_last; - ++__job_counter) - { - // Yes: process it! - __current = __begin + __current_job; - ++__current_job; - - // Do actual work. - __result = __r(__result, __f(__op, __current)); - } + // Thread has own work to do + while (__my_job._M_first <= __my_job._M_last) + { + // fetch-and-add call + // Reserve current job block (size __chunk_size) in my queue. + _DifferenceType __current_job = + __fetch_and_add<_DifferenceType>(&(__my_job._M_first), + __chunk_size); + + // Update _M_load, to make the three values consistent, + // _M_first might have been changed in the meantime + __my_job._M_load = __my_job._M_last - __my_job._M_first + 1; + for (_DifferenceType __job_counter = 0; + __job_counter < __chunk_size + && __current_job <= __my_job._M_last; + ++__job_counter) + { + // Yes: process it! + __current = __begin + __current_job; + ++__current_job; + + // Do actual work. + __result = __r(__result, __f(__op, __current)); + } # pragma omp flush(__busy) - } + } - // After reaching this point, a thread's __job list is empty. - if (__iam_working) - { - // This thread no longer has work. + // After reaching this point, a thread's __job list is empty. + if (__iam_working) + { + // This thread no longer has work. # pragma omp atomic - --__busy; + --__busy; - __iam_working = false; - } + __iam_working = false; + } - _DifferenceType __supposed_first, __supposed_last, __supposed_load; - do - { - // Find random nonempty deque (not own), do consistency check. - __yield(); + _DifferenceType __supposed_first, __supposed_last, + __supposed_load; + do + { + // Find random nonempty deque (not own), do consistency check. + __yield(); # pragma omp flush(__busy) - __victim = rand_gen(); - __supposed_first = __job[__victim * __stride]._M_first; - __supposed_last = __job[__victim * __stride]._M_last; - __supposed_load = __job[__victim * __stride]._M_load; - } - while (__busy > 0 - && ((__supposed_load <= 0) - || ((__supposed_first + __supposed_load - 1) - != __supposed_last))); - - if (__busy == 0) - break; - - if (__supposed_load > 0) - { - // Has work and work to do. - // Number of elements to steal (at least one). - __steal = (__supposed_load < 2) ? 1 : __supposed_load / 2; - - // Push __victim's current start forward. - _DifferenceType __stolen_first = - __fetch_and_add<_DifferenceType>( - &(__job[__victim * __stride]._M_first), __steal); - _DifferenceType __stolen_try = - __stolen_first + __steal - _DifferenceType(1); - - __my_job._M_first = __stolen_first; - __my_job._M_last = - __gnu_parallel::min(__stolen_try, __supposed_last); - __my_job._M_load = __my_job._M_last - __my_job._M_first + 1; - - // Has potential work again. + __victim = __rand_gen(); + __supposed_first = __job[__victim * __stride]._M_first; + __supposed_last = __job[__victim * __stride]._M_last; + __supposed_load = __job[__victim * __stride]._M_load; + } + while (__busy > 0 + && ((__supposed_load <= 0) + || ((__supposed_first + __supposed_load - 1) + != __supposed_last))); + + if (__busy == 0) + break; + + if (__supposed_load > 0) + { + // Has work and work to do. + // Number of elements to steal (at least one). + __steal = (__supposed_load < 2) ? 1 : __supposed_load / 2; + + // Push __victim's current start forward. + _DifferenceType __stolen_first = + __fetch_and_add<_DifferenceType> + (&(__job[__victim * __stride]._M_first), __steal); + _DifferenceType __stolen_try = (__stolen_first + __steal + - _DifferenceType(1)); + + __my_job._M_first = __stolen_first; + __my_job._M_last = __gnu_parallel::min(__stolen_try, + __supposed_last); + __my_job._M_load = __my_job._M_last - __my_job._M_first + 1; + + // Has potential work again. # pragma omp atomic - ++__busy; - __iam_working = true; + ++__busy; + __iam_working = true; # pragma omp flush(__busy) - } + } # pragma omp flush(__busy) - } // end while __busy > 0 - // Add accumulated result to output. - omp_set_lock(&__output_lock); - __output = __r(__output, __result); - omp_unset_lock(&__output_lock); + } // end while __busy > 0 + // Add accumulated result to output. + omp_set_lock(&__output_lock); + __output = __r(__output, __result); + omp_unset_lock(&__output_lock); } - delete[] __job; + delete[] __job; - // Points to last element processed (needed as return value for - // some algorithms like transform) - __f._M_finish_iterator = __begin + __length; + // Points to last element processed (needed as return value for + // some algorithms like transform) + __f._M_finish_iterator = __begin + __length; - omp_destroy_lock(&__output_lock); + omp_destroy_lock(&__output_lock); - return __op; - } + return __op; + } } // end namespace #endif /* _GLIBCXX_PARALLEL_WORKSTEALING_H */ diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h index 1c615091bdc..99def363142 100644 --- a/libstdc++-v3/include/precompiled/stdc++.h +++ b/libstdc++-v3/include/precompiled/stdc++.h @@ -101,6 +101,7 @@ #include <condition_variable> #include <forward_list> #include <future> +#include <initializer_list> #include <mutex> #include <random> #include <ratio> diff --git a/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h b/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h index 2192879325e..bfbafc14f90 100644 --- a/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h +++ b/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h @@ -28,7 +28,7 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/** @file profile/impl/profiler_hashtable_size.cc +/** @file profile/impl/profiler_hashtable_size.h * @brief Collection of hashtable size traces. */ diff --git a/libstdc++-v3/include/profile/impl/profiler_state.h b/libstdc++-v3/include/profile/impl/profiler_state.h index 64c10db616c..03065715463 100644 --- a/libstdc++-v3/include/profile/impl/profiler_state.h +++ b/libstdc++-v3/include/profile/impl/profiler_state.h @@ -28,7 +28,7 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/** @file profile/impl/profiler_state.cc +/** @file profile/impl/profiler_state.h * @brief Global profiler state. */ diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono index aa4888d9a9d..e80ec13c093 100644 --- a/libstdc++-v3/include/std/chrono +++ b/libstdc++-v3/include/std/chrono @@ -138,9 +138,20 @@ namespace std } }; + template<typename _Tp> + struct __is_duration + : std::false_type + { }; + + template<typename _Rep, typename _Period> + struct __is_duration<duration<_Rep, _Period>> + : std::true_type + { }; + /// duration_cast template<typename _ToDuration, typename _Rep, typename _Period> - inline _ToDuration + inline typename enable_if<__is_duration<_ToDuration>::value, + _ToDuration>::type duration_cast(const duration<_Rep, _Period>& __d) { typedef typename @@ -175,16 +186,6 @@ namespace std { return numeric_limits<_Rep>::min(); } }; - template<typename _Tp> - struct __is_duration - : std::false_type - { }; - - template<typename _Rep, typename _Period> - struct __is_duration<duration<_Rep, _Period>> - : std::true_type - { }; - template<typename T> struct __is_ratio : std::false_type @@ -210,24 +211,19 @@ namespace std // 20.8.3.1 construction / copy / destroy duration() = default; - template<typename _Rep2> + template<typename _Rep2, typename = typename + enable_if<is_convertible<_Rep2, rep>::value + && (treat_as_floating_point<rep>::value + || !treat_as_floating_point<_Rep2>::value)>::type> explicit duration(const _Rep2& __rep) - : __r(static_cast<rep>(__rep)) - { - static_assert(is_convertible<_Rep2,rep>::value - && (treat_as_floating_point<rep>::value - || !treat_as_floating_point<_Rep2>::value), - "cannot construct integral duration with floating point type"); - } + : __r(static_cast<rep>(__rep)) { } - template<typename _Rep2, typename _Period2> + template<typename _Rep2, typename _Period2, typename = typename + enable_if<treat_as_floating_point<rep>::value + || (ratio_divide<_Period2, period>::type::den == 1 + && !treat_as_floating_point<_Rep2>::value)>::type> duration(const duration<_Rep2, _Period2>& __d) - : __r(duration_cast<duration>(__d).count()) - { - static_assert(treat_as_floating_point<rep>::value == true - || ratio_divide<_Period2, period>::type::den == 1, - "the resulting duration is not exactly representable"); - } + : __r(duration_cast<duration>(__d).count()) { } ~duration() = default; duration(const duration&) = default; @@ -358,8 +354,17 @@ namespace std return __ct(__lhs) -= __rhs; } + template<typename _Rep1, typename _Rep2, bool = + is_convertible<_Rep2, + typename common_type<_Rep1, _Rep2>::type>::value> + struct __common_rep_type { }; + + template<typename _Rep1, typename _Rep2> + struct __common_rep_type<_Rep1, _Rep2, true> + { typedef typename common_type<_Rep1, _Rep2>::type type; }; + template<typename _Rep1, typename _Period, typename _Rep2> - inline duration<typename common_type<_Rep1, _Rep2>::type, _Period> + inline duration<typename __common_rep_type<_Rep1, _Rep2>::type, _Period> operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) { typedef typename common_type<_Rep1, _Rep2>::type __cr; @@ -367,12 +372,12 @@ namespace std } template<typename _Rep1, typename _Period, typename _Rep2> - inline duration<typename common_type<_Rep1, _Rep2>::type, _Period> - operator*(const _Rep2& __s, const duration<_Rep1, _Period>& __d) + inline duration<typename __common_rep_type<_Rep2, _Rep1>::type, _Period> + operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) { return __d * __s; } template<typename _Rep1, typename _Period, typename _Rep2> - inline duration<typename common_type<_Rep1, typename + inline duration<typename __common_rep_type<_Rep1, typename enable_if<!__is_duration<_Rep2>::value, _Rep2>::type>::type, _Period> operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) { @@ -393,7 +398,7 @@ namespace std // DR 934. template<typename _Rep1, typename _Period, typename _Rep2> - inline duration<typename common_type<_Rep1, typename + inline duration<typename __common_rep_type<_Rep1, typename enable_if<!__is_duration<_Rep2>::value, _Rep2>::type>::type, _Period> operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) { @@ -540,7 +545,8 @@ namespace std /// time_point_cast template<typename _ToDuration, typename _Clock, typename _Duration> - inline time_point<_Clock, _ToDuration> + inline typename enable_if<__is_duration<_ToDuration>::value, + time_point<_Clock, _ToDuration>>::type time_point_cast(const time_point<_Clock, _Duration>& __t) { return time_point<_Clock, _ToDuration>( diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index badb6e07e5a..b8c54b6075f 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -79,7 +79,7 @@ namespace std */ class future_error : public logic_error { - error_code _M_code; + error_code _M_code; public: explicit future_error(future_errc __ec) @@ -96,250 +96,286 @@ namespace std }; // Forward declarations. - template<typename _Result> + template<typename _Res> class unique_future; - template<typename _Result> + template<typename _Res> class shared_future; template<typename> class packaged_task; - template<typename _Result> + template<typename _Res> class promise; #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \ && defined(_GLIBCXX_ATOMIC_BUILTINS_4) - // Holds the result of a future - struct _Future_result_base + /// Base class and enclosing scope. + struct __future_base { - _Future_result_base() = default; - _Future_result_base(const _Future_result_base&) = delete; - _Future_result_base& operator=(const _Future_result_base&) = delete; + /// Base class for results. + struct _Result_base + { + exception_ptr _M_error; - exception_ptr _M_error; + _Result_base() = default; + _Result_base(const _Result_base&) = delete; + _Result_base& operator=(const _Result_base&) = delete; - // _M_destroy() allows derived classes to control deallocation, - // which will be needed when allocator support is added to promise. - // See http://gcc.gnu.org/ml/libstdc++/2009-06/msg00032.html - virtual void _M_destroy() = 0; - struct _Deleter - { - void operator()(_Future_result_base* __fr) const { __fr->_M_destroy(); } - }; + // _M_destroy() allows derived classes to control deallocation, + // which will be needed when allocator support is added to promise. + // See http://gcc.gnu.org/ml/libstdc++/2009-06/msg00032.html + virtual void _M_destroy() = 0; - protected: - ~_Future_result_base() = default; - }; + struct _Deleter + { + void operator()(_Result_base* __fr) const { __fr->_M_destroy(); } + }; - // TODO: use template alias when available - /* - template<typename _Res> - using _Future_ptr = unique_ptr<_Res, _Future_result_base::_Deleter>; - */ - template<typename _Res> - struct _Future_ptr - { - typedef unique_ptr<_Res, _Future_result_base::_Deleter> type; + protected: + ~_Result_base(); }; - // State shared between a promise and one or more associated futures. - class _Future_state - { - typedef _Future_ptr<_Future_result_base>::type _Future_ptr_type; + /// Result. + template<typename _Res> + struct _Result : _Result_base + { + private: + typedef alignment_of<_Res> __a_of; + typedef aligned_storage<sizeof(_Res), __a_of::value> __align_storage; + typedef typename __align_storage::type __align_type; + + __align_type _M_storage; + bool _M_initialized; + + public: + _Result() : _M_initialized() { } + + ~_Result() + { + if (_M_initialized) + _M_value().~_Res(); + } + + // Return lvalue, future will add const or rvalue-reference + _Res& + _M_value() { return *static_cast<_Res*>(_M_addr()); } + + void + _M_set(const _Res& __res) + { + ::new (_M_addr()) _Res(__res); + _M_initialized = true; + } + + void + _M_set(_Res&& __res) + { + ::new (_M_addr()) _Res(_Move_result<_Res>::_S_move(__res)); + _M_initialized = true; + } + + private: + void _M_destroy() { delete this; } + + void* _M_addr() { return static_cast<void*>(&_M_storage); } + }; - public: - _Future_state() : _M_result(), _M_retrieved(false) { } - _Future_state(const _Future_state&) = delete; - _Future_state& operator=(const _Future_state&) = delete; + /// Workaround for CWG issue 664 and c++/34022 + template<typename _Res, bool = is_scalar<_Res>::value> + struct _Move_result; - bool - is_ready() - { return _M_get() != 0; } + /// Specialization for scalar types returns rvalue not rvalue-reference. + template<typename _Res> + struct _Move_result<_Res, true> + { + typedef _Res __rval_type; + static _Res _S_move(_Res __res) { return __res; } + }; + + /// Specialization for non-scalar types returns rvalue-reference. + template<typename _Res> + struct _Move_result<_Res, false> + { + typedef _Res&& __rval_type; + static _Res&& _S_move(_Res& __res) { return std::move(__res); } + }; + + + // TODO: use template alias when available + /* + template<typename _Res> + using _Ptr = unique_ptr<_Res, _Result_base::_Deleter>; + */ + /// A unique_ptr based on the instantiating type. + template<typename _Res> + struct _Ptr + { + typedef unique_ptr<_Res, _Result_base::_Deleter> type; + }; - bool - has_exception() - { - _Future_result_base* const __res = _M_get(); - return __res && !(__res->_M_error == 0); - } - bool - has_value() + /// Shared state between a promise and one or more associated futures. + class _State { - _Future_result_base* const __res = _M_get(); - return __res && (__res->_M_error == 0); - } + typedef _Ptr<_Result_base>::type _Ptr_type; - _Future_result_base& - wait() - { - unique_lock<mutex> __lock(_M_mutex); - if (!_M_ready()) - _M_cond.wait(__lock, std::bind(&_Future_state::_M_ready, this)); - return *_M_result; - } + _Ptr_type _M_result; + mutex _M_mutex; + condition_variable _M_cond; + atomic_flag _M_retrieved; + + public: + _State() : _M_result(), _M_retrieved(ATOMIC_FLAG_INIT) { } + + _State(const _State&) = delete; + _State& operator=(const _State&) = delete; - template<typename _Rep, typename _Period> bool - wait_for(const chrono::duration<_Rep, _Period>& __rel) - { - unique_lock<mutex> __lock(_M_mutex); - return _M_ready() || _M_cond.wait_for(__lock, __rel, - std::bind(&_Future_state::_M_ready, this)); - } + is_ready() + { return _M_get() != 0; } - template<typename _Clock, typename _Duration> bool - wait_until(const chrono::time_point<_Clock, _Duration>& __abs) + has_exception() { - unique_lock<mutex> __lock(_M_mutex); - return _M_ready() || _M_cond.wait_until(__lock, __abs, - std::bind(&_Future_state::_M_ready, this)); + _Result_base* const __res = _M_get(); + return __res && !(__res->_M_error == 0); } - void - _M_set_result(_Future_ptr_type __res) - { + bool + has_value() { - lock_guard<mutex> __lock(_M_mutex); - if (_M_ready()) - __throw_future_error(int(future_errc::promise_already_satisfied)); - _M_result.swap(__res); + _Result_base* const __res = _M_get(); + return __res && (__res->_M_error == 0); } - _M_cond.notify_all(); - } - void - _M_break_promise(_Future_ptr_type __res) - { - if (static_cast<bool>(__res)) + _Result_base& + wait() { - __res->_M_error - = std::copy_exception(future_error(future_errc::broken_promise)); - { - lock_guard<mutex> __lock(_M_mutex); - _M_result.swap(__res); - } - _M_cond.notify_all(); + unique_lock<mutex> __lock(_M_mutex); + if (!_M_ready()) + _M_cond.wait(__lock, std::bind(&_State::_M_ready, this)); + return *_M_result; } - } - // called when this object is passed to a unique_future - void - _M_set_retrieved_flag() - { - if (_M_retrieved.test_and_set()) - __throw_future_error(int(future_errc::future_already_retrieved)); - } - - private: - _Future_result_base* - _M_get() - { - lock_guard<mutex> __lock(_M_mutex); - return _M_result.get(); - } - - bool _M_ready() const { return static_cast<bool>(_M_result); } - - _Future_ptr_type _M_result; - mutex _M_mutex; - condition_variable _M_cond; - atomic_flag _M_retrieved; - }; - - // workaround for CWG issue 664 and c++/34022 - template<typename _Result, bool = is_scalar<_Result>::value> - struct _Move_future_result - { - typedef _Result&& __rval_type; - static _Result&& _S_move(_Result& __res) { return std::move(__res); } - }; - - // specialization for scalar types returns rvalue not rvalue-reference - template<typename _Result> - struct _Move_future_result<_Result, true> - { - typedef _Result __rval_type; - static _Result _S_move(_Result __res) { return __res; } - }; + template<typename _Rep, typename _Period> + bool + wait_for(const chrono::duration<_Rep, _Period>& __rel) + { + unique_lock<mutex> __lock(_M_mutex); + auto __bound = std::bind(&_State::_M_ready, this); + return _M_ready() || _M_cond.wait_for(__lock, __rel, __bound); + } - template<typename _Result> - struct _Future_result : _Future_result_base - { - _Future_result() : _M_initialized() { } + template<typename _Clock, typename _Duration> + bool + wait_until(const chrono::time_point<_Clock, _Duration>& __abs) + { + unique_lock<mutex> __lock(_M_mutex); + auto __bound = std::bind(&_State::_M_ready, this); + return _M_ready() || _M_cond.wait_until(__lock, __abs, __bound); + } - ~_Future_result() + void + _M_set_result(_Ptr_type __res) { - if (_M_initialized) - _M_value().~_Result(); + { + lock_guard<mutex> __lock(_M_mutex); + if (_M_ready()) + __throw_future_error(int(future_errc::promise_already_satisfied)); + _M_result.swap(__res); + } + _M_cond.notify_all(); } - // return lvalue, future will add const or rvalue-reference - _Result& _M_value() - { return *static_cast<_Result*>(_M_addr()); } - void - _M_set(const _Result& __res) + _M_break_promise(_Ptr_type __res) { - ::new (_M_addr()) _Result(__res); - _M_initialized = true; + if (static_cast<bool>(__res)) + { + future_errc __ec(future_errc::broken_promise); // XXX + __res->_M_error = copy_exception(future_error(__ec)); + { + lock_guard<mutex> __lock(_M_mutex); + _M_result.swap(__res); + } + _M_cond.notify_all(); + } } + // Called when this object is passed to a unique_future. void - _M_set(_Result&& __res) + _M_set_retrieved_flag() { - typedef _Move_future_result<_Result> _Mover; - ::new (_M_addr()) _Result(_Mover::_S_move(__res)); - _M_initialized = true; + if (_M_retrieved.test_and_set()) + __throw_future_error(int(future_errc::future_already_retrieved)); } private: - void _M_destroy() { delete this; } - - void* _M_addr() { return static_cast<void*>(&_M_storage); } + _Result_base* + _M_get() + { + lock_guard<mutex> __lock(_M_mutex); + return _M_result.get(); + } - typename aligned_storage<sizeof(_Result), - alignment_of<_Result>::value>::type _M_storage; - bool _M_initialized; + bool _M_ready() const { return static_cast<bool>(_M_result); } }; + }; - template<typename _Result> - struct _Future_result<_Result&> : _Future_result_base - { - _Future_result() : _M_value_ptr() { } + inline __future_base::_Result_base::~_Result_base() = default; - _Result* _M_value_ptr; + /// Partial specialization for reference types. + template<typename _Res> + struct __future_base::_Result<_Res&> : __future_base::_Result_base + { + _Result() : _M_value_ptr() { } + _Res* _M_value_ptr; + + private: void _M_destroy() { delete this; } }; + /// Explicit specialization for void. template<> - struct _Future_result<void> : _Future_result_base + struct __future_base::_Result<void> : __future_base::_Result_base { + private: void _M_destroy() { delete this; } }; - // common implementation for unique_future and shared_future - template<typename _Result> - class _Future_impl + + /// Common implementation for unique_future and shared_future. + template<typename _Res> + class __basic_future : public __future_base { + protected: + typedef shared_ptr<_State> __state_type; + typedef __future_base::_Result<_Res>& __result_type; + + private: + __state_type _M_state; + public: - // disable copying - _Future_impl(const _Future_impl&) = delete; - _Future_impl& operator=(const _Future_impl&) = delete; + // Disable copying. + __basic_future(const __basic_future&) = delete; + __basic_future& operator=(const __basic_future&) = delete; - // functions to check state and wait for ready - bool is_ready() const { return this->_M_state->is_ready(); } + // Functions to check state and wait for ready. + bool + is_ready() const { return this->_M_state->is_ready(); } - bool has_exception() const { return this->_M_state->has_exception(); } + bool + has_exception() const { return this->_M_state->has_exception(); } - bool has_value() const { return this->_M_state->has_value(); } + bool + has_value() const { return this->_M_state->has_value(); } - void wait() const { this->_M_state->wait(); } + void + wait() const { this->_M_state->wait(); } template<typename _Rep, typename _Period> bool @@ -352,22 +388,19 @@ namespace std { return this->_M_state->wait_until(__abs); } protected: - // wait for the state to be ready and rethrow any stored exception - _Future_result<_Result>& + /// Wait for the state to be ready and rethrow any stored exception + __result_type _M_get_result() { - _Future_result_base& __res = this->_M_state->wait(); + _Result_base& __res = this->_M_state->wait(); if (!(__res._M_error == 0)) rethrow_exception(__res._M_error); - return static_cast<_Future_result<_Result>&>(__res); + return static_cast<__result_type>(__res); } - typedef shared_ptr<_Future_state> _State_ptr; - - // construction of a unique_future by promise::get_future() + // Construction of a unique_future by promise::get_future() explicit - _Future_impl(const _State_ptr& __state) - : _M_state(__state) + __basic_future(const __state_type& __state) : _M_state(__state) { if (static_cast<bool>(this->_M_state)) this->_M_state->_M_set_retrieved_flag(); @@ -375,146 +408,149 @@ namespace std __throw_future_error(int(future_errc::future_already_retrieved)); } - // copy construction from a shared_future + // Copy construction from a shared_future explicit - _Future_impl(const shared_future<_Result>&); + __basic_future(const shared_future<_Res>&); - // move construction from a unique_future + // Move construction from a unique_future explicit - _Future_impl(unique_future<_Result>&&); - - _State_ptr _M_state; + __basic_future(unique_future<_Res>&&); }; - /// primary template for unique_future - template<typename _Result> - class unique_future : public _Future_impl<_Result> + + /// Primary template for unique_future. + template<typename _Res> + class unique_future : public __basic_future<_Res> { - typedef _Move_future_result<_Result> _Mover; + friend class promise<_Res>; + + typedef __basic_future<_Res> _Base_type; + typedef typename _Base_type::__state_type __state_type; + typedef __future_base::_Move_result<_Res> _Mover; + + explicit + unique_future(const __state_type& __state) : _Base_type(__state) { } public: /// Move constructor unique_future(unique_future&& __uf) : _Base_type(std::move(__uf)) { } - // disable copying + // Disable copying unique_future(const unique_future&) = delete; unique_future& operator=(const unique_future&) = delete; - // retrieving the value + /// Retrieving the value typename _Mover::__rval_type get() { return _Mover::_S_move(this->_M_get_result()._M_value()); } - - private: - typedef _Future_impl<_Result> _Base_type; - typedef typename _Base_type::_State_ptr _State_ptr; - - friend class promise<_Result>; - - explicit - unique_future(const _State_ptr& __state) : _Base_type(__state) { } }; - // partial specialization for unique_future<R&> - template<typename _Result> - class unique_future<_Result&> : public _Future_impl<_Result&> + /// Partial specialization for unique_future<R&> + template<typename _Res> + class unique_future<_Res&> : public __basic_future<_Res&> { + friend class promise<_Res&>; + + typedef __basic_future<_Res&> _Base_type; + typedef typename _Base_type::__state_type __state_type; + + explicit + unique_future(const __state_type& __state) : _Base_type(__state) { } + public: /// Move constructor unique_future(unique_future&& __uf) : _Base_type(std::move(__uf)) { } - // disable copying + // Disable copying unique_future(const unique_future&) = delete; unique_future& operator=(const unique_future&) = delete; - // retrieving the value - _Result& get() { return *this->_M_get_result()._M_value_ptr; } + /// Retrieving the value + _Res& + get() { return *this->_M_get_result()._M_value_ptr; } + }; - private: - typedef _Future_impl<_Result&> _Base_type; - typedef typename _Base_type::_State_ptr _State_ptr; + /// Explicit specialization for unique_future<void> + template<> + class unique_future<void> : public __basic_future<void> + { + friend class promise<void>; - friend class promise<_Result&>; + typedef __basic_future<void> _Base_type; + typedef typename _Base_type::__state_type __state_type; explicit - unique_future(const _State_ptr& __state) : _Base_type(__state) { } - }; + unique_future(const __state_type& __state) : _Base_type(__state) { } - // specialization for unique_future<void> - template<> - class unique_future<void> : public _Future_impl<void> - { public: /// Move constructor unique_future(unique_future&& __uf) : _Base_type(std::move(__uf)) { } - // disable copying + // Disable copying unique_future(const unique_future&) = delete; unique_future& operator=(const unique_future&) = delete; - // retrieving the value - void get() { this->_M_get_result(); } - - private: - typedef _Future_impl<void> _Base_type; - typedef _Base_type::_State_ptr _State_ptr; - - friend class promise<void>; - - explicit - unique_future(const _State_ptr& __state) : _Base_type(__state) { } + /// Retrieving the value + void + get() { this->_M_get_result(); } }; - /// primary template for shared_future - template<typename _Result> - class shared_future : public _Future_impl<_Result> + + /// Primary template for shared_future. + template<typename _Res> + class shared_future : public __basic_future<_Res> { + typedef __basic_future<_Res> _Base_type; + public: /// Copy constructor shared_future(const shared_future& __sf) : _Base_type(__sf) { } /// Construct from a unique_future rvalue - shared_future(unique_future<_Result>&& __uf) + shared_future(unique_future<_Res>&& __uf) : _Base_type(std::move(__uf)) { } shared_future& operator=(const shared_future&) = delete; - // retrieving the value - const _Result& + /// Retrieving the value + const _Res& get() - { return this->_M_get_result()._M_value(); } - - private: - typedef _Future_impl<_Result> _Base_type; + { + typename _Base_type::__result_type __r = this->_M_get_result(); + _Res& __rs(__r._M_value()); + return __rs; + } }; - // partial specialization for shared_future<R&> - template<typename _Result> - class shared_future<_Result&> : public _Future_impl<_Result&> + /// Partial specialization for shared_future<R&> + template<typename _Res> + class shared_future<_Res&> : public __basic_future<_Res&> { + typedef __basic_future<_Res&> _Base_type; + public: /// Copy constructor shared_future(const shared_future& __sf) : _Base_type(__sf) { } /// Construct from a unique_future rvalue - shared_future(unique_future<_Result&>&& __uf) + shared_future(unique_future<_Res&>&& __uf) : _Base_type(std::move(__uf)) { } shared_future& operator=(const shared_future&) = delete; - // retrieving the value - _Result& get() { return *this->_M_get_result()._M_value_ptr; } - - private: - typedef _Future_impl<_Result&> _Base_type; + /// Retrieving the value + _Res& + get() { return *this->_M_get_result()._M_value_ptr; } }; - // specialization for shared_future<void> + /// Explicit specialization for shared_future<void> template<> - class shared_future<void> : public _Future_impl<void> + class shared_future<void> : public __basic_future<void> { + typedef __basic_future<void> _Base_type; + public: /// Copy constructor shared_future(const shared_future& __sf) : _Base_type(__sf) { } @@ -526,33 +562,39 @@ namespace std shared_future& operator=(const shared_future&) = delete; - // retrieving the value - void get() { this->_M_get_result(); } - - private: - typedef _Future_impl<void> _Base_type; + // Retrieving the value + void + get() { this->_M_get_result(); } }; - // now we can define the protected _Future_impl constructors - - template<typename _Result> - _Future_impl<_Result>::_Future_impl(const shared_future<_Result>& __sf) + // Now we can define the protected __basic_future constructors. + template<typename _Res> + __basic_future<_Res>::__basic_future(const shared_future<_Res>& __sf) : _M_state(__sf._M_state) { } - template<typename _Result> - _Future_impl<_Result>::_Future_impl(unique_future<_Result>&& __uf) + template<typename _Res> + __basic_future<_Res>::__basic_future(unique_future<_Res>&& __uf) : _M_state(std::move(__uf._M_state)) { } - /// primary template for promise - template<typename _Result> + + /// Primary template for promise + template<typename _Res> class promise { + template<typename> friend class packaged_task; + + typedef __future_base::_State _State; + typedef __future_base::_Move_result<_Res> _Mover; + typedef __future_base::_Result<_Res> result_type; + + shared_ptr<_State> _M_future; + typename __future_base::_Ptr<result_type>::type _M_storage; + public: promise() - : _M_future(std::make_shared<_Future_state>()), - _M_storage(new _Future_result<_Result>()) + : _M_future(std::make_shared<_State>()), _M_storage(new result_type()) { } promise(promise&& __rhs) @@ -577,7 +619,7 @@ namespace std _M_future->_M_break_promise(std::move(_M_storage)); } - // assignment + // Assignment promise& operator=(promise&& __rhs) { @@ -594,14 +636,14 @@ namespace std _M_storage.swap(__rhs._M_storage); } - // retrieving the result - unique_future<_Result> + // Retrieving the result + unique_future<_Res> get_future() - { return unique_future<_Result>(_M_future); } + { return unique_future<_Res>(_M_future); } - // setting the result + // Setting the result void - set_value(const _Result& __r) + set_value(const _Res& __r) { if (!_M_satisfied()) _M_storage->_M_set(__r); @@ -609,7 +651,7 @@ namespace std } void - set_value(_Result&& __r) + set_value(_Res&& __r) { if (!_M_satisfied()) _M_storage->_M_set(_Mover::_S_move(__r)); @@ -625,26 +667,29 @@ namespace std } private: - template<typename> friend class packaged_task; - typedef _Move_future_result<_Result> _Mover; bool _M_satisfied() { return !static_cast<bool>(_M_storage); } - shared_ptr<_Future_state> _M_future; - typename _Future_ptr<_Future_result<_Result>>::type _M_storage; }; - // partial specialization for promise<R&> - template<typename _Result> - class promise<_Result&> + /// Partial specialization for promise<R&> + template<typename _Res> + class promise<_Res&> { + template<typename> friend class packaged_task; + typedef __future_base::_State _State; + + typedef __future_base::_Result<_Res&> result_type; + + shared_ptr<_State> _M_future; + typename __future_base::_Ptr<result_type>::type _M_storage; + public: promise() - : _M_future(std::make_shared<_Future_state>()), - _M_storage(new _Future_result<_Result&>()) + : _M_future(std::make_shared<_State>()), _M_storage(new result_type()) { } promise(promise&& __rhs) - : _M_future(std::move(__rhs._M_future)), - _M_storage(std::move(__rhs._M_storage)) + : _M_future(std::move(__rhs._M_future)), + _M_storage(std::move(__rhs._M_storage)) { } // TODO: requires allocator concepts @@ -664,7 +709,7 @@ namespace std _M_future->_M_break_promise(std::move(_M_storage)); } - // assignment + // Assignment promise& operator=(promise&& __rhs) { @@ -681,14 +726,14 @@ namespace std _M_storage.swap(__rhs._M_storage); } - // retrieving the result - unique_future<_Result&> + // Retrieving the result + unique_future<_Res&> get_future() - { return unique_future<_Result&>(_M_future); } + { return unique_future<_Res&>(_M_future); } - // setting the result + // Setting the result void - set_value(_Result& __r) + set_value(_Res& __r) { if (!_M_satisfied()) _M_storage->_M_value_ptr = &__r; @@ -704,20 +749,24 @@ namespace std } private: - template<typename> friend class packaged_task; bool _M_satisfied() { return !static_cast<bool>(_M_storage); } - shared_ptr<_Future_state> _M_future; - typename _Future_ptr<_Future_result<_Result&>>::type _M_storage; }; - // specialization for promise<void> + /// Explicit specialization for promise<void> template<> class promise<void> { + template<typename> friend class packaged_task; + typedef __future_base::_State _State; + typedef __future_base::_Result<void> result_type; + + shared_ptr<__future_base::_State> _M_future; + typename __future_base::_Ptr<result_type>::type _M_storage; + public: promise() - : _M_future(std::make_shared<_Future_state>()), - _M_storage(new _Future_result<void>()) + : _M_future(std::make_shared<_State>()), + _M_storage(new result_type()) { } promise(promise&& __rhs) @@ -742,7 +791,7 @@ namespace std _M_future->_M_break_promise(std::move(_M_storage)); } - // assignment + // Assignment promise& operator=(promise&& __rhs) { @@ -759,12 +808,12 @@ namespace std _M_storage.swap(__rhs._M_storage); } - // retrieving the result + // Retrieving the result unique_future<void> get_future() { return unique_future<void>(_M_future); } - // setting the result + // Setting the result void set_value() { @@ -780,53 +829,54 @@ namespace std } private: - template<typename> friend class packaged_task; bool _M_satisfied() { return !static_cast<bool>(_M_storage); } - shared_ptr<_Future_state> _M_future; - _Future_ptr<_Future_result<void>>::type _M_storage; }; // TODO: requires allocator concepts /* - template<typename _Result, class Alloc> - concept_map UsesAllocator<promise<_Result>, Alloc> + template<typename _Res, class Alloc> + concept_map UsesAllocator<promise<_Res>, Alloc> { typedef Alloc allocator_type; } */ - - template<typename _Result, typename... _ArgTypes> + /// Primary template. + template<typename _Res, typename... _ArgTypes> struct _Run_task { static void - _S_run(promise<_Result>& __p, function<_Result(_ArgTypes...)>& __f, - _ArgTypes... __args) + _S_run(promise<_Res>& __p, function<_Res(_ArgTypes...)>& __f, + _ArgTypes... __args) { __p.set_value(__f(std::forward<_ArgTypes>(__args)...)); } }; - // specialization used by packaged_task<void(...)> + /// Specialization used by packaged_task<void(...)> template<typename... _ArgTypes> struct _Run_task<void, _ArgTypes...> { static void _S_run(promise<void>& __p, function<void(_ArgTypes...)>& __f, - _ArgTypes... __args) + _ArgTypes... __args) { __f(std::forward<_ArgTypes>(__args)...); __p.set_value(); } }; + /// packaged_task - template<typename _Result, typename... _ArgTypes> - class packaged_task<_Result(_ArgTypes...)> + template<typename _Res, typename... _ArgTypes> + class packaged_task<_Res(_ArgTypes...)> { + function<_Res(_ArgTypes...)> _M_task; + promise<_Res> _M_promise; + public: - typedef _Result result_type; + typedef _Res result_type; - // construction and destruction + // Construction and destruction packaged_task() { } template<typename _Fn> @@ -838,7 +888,7 @@ namespace std packaged_task(_Fn&& __fn) : _M_task(std::move(__fn)) { } explicit - packaged_task(_Result(*__fn)(_ArgTypes...)) : _M_task(__fn) { } + packaged_task(_Res(*__fn)(_ArgTypes...)) : _M_task(__fn) { } // TODO: requires allocator concepts /* @@ -857,11 +907,11 @@ namespace std ~packaged_task() = default; - // no copy + // No copy packaged_task(packaged_task&) = delete; packaged_task& operator=(packaged_task&) = delete; - // move support + // Move support packaged_task(packaged_task&& __other) { this->swap(__other); } @@ -880,8 +930,8 @@ namespace std explicit operator bool() const { return static_cast<bool>(_M_task); } - // result retrieval - unique_future<_Result> + // Result retrieval + unique_future<_Res> get_future() { __try @@ -898,7 +948,7 @@ namespace std } } - // execution + // Execution void operator()(_ArgTypes... __args) { @@ -913,7 +963,7 @@ namespace std __try { - _Run_task<_Result, _ArgTypes...>::_S_run(_M_promise, _M_task, + _Run_task<_Res, _ArgTypes...>::_S_run(_M_promise, _M_task, std::forward<_ArgTypes>(__args)...); } __catch (...) @@ -922,11 +972,7 @@ namespace std } } - void reset() { promise<_Result>().swap(_M_promise); } - - private: - function<_Result(_ArgTypes...)> _M_task; - promise<_Result> _M_promise; + void reset() { promise<_Res>().swap(_M_promise); } }; #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 diff --git a/libstdc++-v3/include/std/iosfwd b/libstdc++-v3/include/std/iosfwd index 9bba0ab6bfc..b3405d7f1d5 100644 --- a/libstdc++-v3/include/std/iosfwd +++ b/libstdc++-v3/include/std/iosfwd @@ -43,6 +43,36 @@ _GLIBCXX_BEGIN_NAMESPACE(std) + /** + * @defgroup io I/O + * + * Nearly all of the I/O classes are parameterized on the type of + * characters they read and write. (The major exception is ios_base at + * the top of the hierarchy.) This is a change from pre-Standard + * streams, which were not templates. + * + * For ease of use and compatibility, all of the basic_* I/O-related + * classes are given typedef names for both of the builtin character + * widths (wide and narrow). The typedefs are the same as the + * pre-Standard names, for example: + * + * @code + * typedef basic_ifstream<char> ifstream; + * @endcode + * + * Because properly forward-declaring these classes can be difficult, you + * should not do it yourself. Instead, include the <iosfwd> + * header, which contains only declarations of all the I/O classes as + * well as the typedefs. Trying to forward-declare the typedefs + * themselves (e.g., "class ostream;") is not valid ISO C++. + * + * For more specific declarations, see + * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch24.html + * + * @{ + */ + class ios_base; + template<typename _CharT, typename _Traits = char_traits<_CharT> > class basic_ios; @@ -94,36 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // _GLIBCXX_RESOLVE_LIB_DEFECTS // Not included. (??? Apparently no LWG number?) - class ios_base; - /** - * @defgroup io I/O - * - * Nearly all of the I/O classes are parameterized on the type of - * characters they read and write. (The major exception is ios_base at - * the top of the hierarchy.) This is a change from pre-Standard - * streams, which were not templates. - * - * For ease of use and compatibility, all of the basic_* I/O-related - * classes are given typedef names for both of the builtin character - * widths (wide and narrow). The typedefs are the same as the - * pre-Standard names, for example: - * - * @code - * typedef basic_ifstream<char> ifstream; - * @endcode - * - * Because properly forward-declaring these classes can be difficult, you - * should not do it yourself. Instead, include the <iosfwd> - * header, which contains only declarations of all the I/O classes as - * well as the typedefs. Trying to forward-declare the typedefs - * themselves (e.g., "class ostream;") is not valid ISO C++. - * - * For more specific declarations, see - * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch24.html - * - * @{ - */ typedef basic_ios<char> ios; ///< @isiosfwd typedef basic_streambuf<char> streambuf; ///< @isiosfwd typedef basic_istream<char> istream; ///< @isiosfwd diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits index 41bf806d5eb..1f3f078d0f0 100644 --- a/libstdc++-v3/include/std/limits +++ b/libstdc++-v3/include/std/limits @@ -203,9 +203,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * Is this supposed to be "if the type is integral"? */ static const bool is_integer = false; - /** True if the type uses an exact representation. "All integer types are + /** True if the type uses an exact representation. 'All integer types are exact, but not all exact types are integer. For example, rational and - fixed-exponent representations are exact but not integer." + fixed-exponent representations are exact but not integer.' [18.2.1.2]/15 */ static const bool is_exact = false; /** For integer types, specifies the base of the representation. For @@ -229,23 +229,23 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /** True if the type has a representation for positive infinity. */ static const bool has_infinity = false; /** True if the type has a representation for a quiet (non-signaling) - "Not a Number." */ + 'Not a Number.' */ static const bool has_quiet_NaN = false; /** True if the type has a representation for a signaling - "Not a Number." */ + 'Not a Number.' */ static const bool has_signaling_NaN = false; /** See std::float_denorm_style for more information. */ static const float_denorm_style has_denorm = denorm_absent; - /** "True if loss of accuracy is detected as a denormalization loss, - rather than as an inexact result." [18.2.1.2]/42 */ + /** 'True if loss of accuracy is detected as a denormalization loss, + rather than as an inexact result.' [18.2.1.2]/42 */ static const bool has_denorm_loss = false; /** True if-and-only-if the type adheres to the IEC 559 standard, also known as IEEE 754. (Only makes sense for floating point types.) */ static const bool is_iec559 = false; - /** "True if the set of values representable by the type is finite. All + /** 'True if the set of values representable by the type is finite. All built-in types are bounded, this member would be false for arbitrary - precision types." [18.2.1.2]/54 */ + precision types.' [18.2.1.2]/54 */ static const bool is_bounded = false; /** True if the type is @e modulo, that is, if it is possible to add two positive numbers and have a result that wraps around to a third number diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory index 9defd487c60..3e7d4e8466b 100644 --- a/libstdc++-v3/include/std/memory +++ b/libstdc++-v3/include/std/memory @@ -46,6 +46,20 @@ #pragma GCC system_header +/** + * @defgroup memory Memory + * @ingroup utilities + * + * Components for memory allocation, deallocation, and management. + */ + +/** + * @defgroup pointer_abstractions Pointer Abstractions + * @ingroup memory + * + * Smart pointers, etc. + */ + #include <bits/stl_algobase.h> #include <bits/allocator.h> #include <bits/stl_construct.h> @@ -64,37 +78,29 @@ # include <ext/concurrence.h> # include <bits/functexcept.h> # include <bits/stl_function.h> // std::less -# include <bits/unique_ptr.h> -# include <debug/debug.h> # include <type_traits> # include <functional> +# include <debug/debug.h> +# include <bits/unique_ptr.h> # if _GLIBCXX_DEPRECATED # include <backward/auto_ptr.h> # endif # if defined(_GLIBCXX_INCLUDE_AS_CXX0X) # include <tr1_impl/boost_sp_counted_base.h> -# include <bits/shared_ptr.h> # else # define _GLIBCXX_INCLUDE_AS_CXX0X # define _GLIBCXX_BEGIN_NAMESPACE_TR1 # define _GLIBCXX_END_NAMESPACE_TR1 # define _GLIBCXX_TR1 # include <tr1_impl/boost_sp_counted_base.h> -# include <bits/shared_ptr.h> # undef _GLIBCXX_TR1 # undef _GLIBCXX_END_NAMESPACE_TR1 # undef _GLIBCXX_BEGIN_NAMESPACE_TR1 # undef _GLIBCXX_INCLUDE_AS_CXX0X # endif +# include <bits/shared_ptr.h> #else # include <backward/auto_ptr.h> #endif -/** - * @defgroup memory Memory - * @ingroup utilities - * - * Components for memory allocation, deallocation, and management. - */ - #endif /* _GLIBCXX_MEMORY */ diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index 9fc693cb3c3..d6241ba39a2 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -533,8 +533,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * * This manipulator is often mistakenly used when a simple newline is * desired, leading to poor buffering performance. See - * http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#2 for more - * on this subject. + * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt11ch25s02.html + * for more on this subject. */ template<typename _CharT, typename _Traits> inline basic_ostream<_CharT, _Traits>& diff --git a/libstdc++-v3/include/std/random b/libstdc++-v3/include/std/random index b57ef4925d6..72d3ceb7f43 100644 --- a/libstdc++-v3/include/std/random +++ b/libstdc++-v3/include/std/random @@ -43,7 +43,6 @@ #include <limits> #include <ext/type_traits.h> #include <ext/numeric_traits.h> -#include <bits/concept_check.h> #include <debug/debug.h> #include <type_traits> diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream index f5e3191c4cd..0ebf506d0c7 100644 --- a/libstdc++-v3/include/std/sstream +++ b/libstdc++-v3/include/std/sstream @@ -112,9 +112,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * @brief Copying out the string buffer. * @return A copy of one of the underlying sequences. * - * "If the buffer is only created in input mode, the underlying + * 'If the buffer is only created in input mode, the underlying * character sequence is equal to the input sequence; otherwise, it - * is equal to the output sequence." [27.7.1.2]/1 + * is equal to the output sequence.' [27.7.1.2]/1 */ __string_type str() const diff --git a/libstdc++-v3/include/std/streambuf b/libstdc++-v3/include/std/streambuf index 790be0ec4d4..7d6b8c789cb 100644 --- a/libstdc++-v3/include/std/streambuf +++ b/libstdc++-v3/include/std/streambuf @@ -341,7 +341,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * @return The previous character, if possible. * * Similar to sungetc(), but @a c is pushed onto the stream instead - * of "the previous character". If successful, the next character + * of 'the previous character.' If successful, the next character * fetched from the input stream will be @a c. */ int_type @@ -366,8 +366,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * * If a putback position is available, this function decrements the * input pointer and returns that character. Otherwise, calls and - * returns pbackfail(). The effect is to "unget" the last character - * "gotten". + * returns pbackfail(). The effect is to 'unget' the last character + * 'gotten.' */ int_type sungetc() @@ -541,10 +541,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * @param loc A new locale. * * Translations done during I/O which depend on the current locale - * are changed by this call. The standard adds, "Between invocations + * are changed by this call. The standard adds, 'Between invocations * of this function a class derived from streambuf can safely cache * results of calls to locale functions and to members of facets - * so obtained." + * so obtained.' * * @note Base class version does nothing. */ @@ -608,18 +608,18 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * @return An estimate of the number of characters available in the * input sequence, or -1. * - * "If it returns a positive value, then successive calls to + * 'If it returns a positive value, then successive calls to * @c underflow() will not return @c traits::eof() until at least that * number of characters have been supplied. If @c showmanyc() - * returns -1, then calls to @c underflow() or @c uflow() will fail." + * returns -1, then calls to @c underflow() or @c uflow() will fail.' * [27.5.2.4.3]/1 * * @note Base class version does nothing, returns zero. - * @note The standard adds that "the intention is not only that the + * @note The standard adds that 'the intention is not only that the * calls [to underflow or uflow] will not return @c eof() but - * that they will return "immediately". - * @note The standard adds that "the morphemes of @c showmanyc are - * "es-how-many-see", not "show-manic". + * that they will return immediately.' + * @note The standard adds that 'the morphemes of @c showmanyc are + * 'es-how-many-see', not 'show-manic'.' */ virtual streamsize showmanyc() { return 0; } @@ -646,7 +646,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * * Informally, this function is called when the input buffer is * exhausted (or does not exist, as buffering need not actually be - * done). If a buffer exists, it is "refilled". In either case, the + * done). If a buffer exists, it is 'refilled'. In either case, the * next available character is returned, or @c traits::eof() to * indicate a null pending sequence. * @@ -690,7 +690,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /** * @brief Tries to back up the input sequence. * @param c The character to be inserted back into the sequence. - * @return eof() on failure, "some other value" on success + * @return eof() on failure, 'some other value' on success * @post The constraints of @c gptr(), @c eback(), and @c pptr() * are the same as for @c underflow(). * @@ -726,7 +726,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * * Informally, this function is called when the output buffer is full * (or does not exist, as buffering need not actually be done). If a - * buffer exists, it is "consumed", with "some effect" on the + * buffer exists, it is 'consumed', with 'some effect' on the * controlled sequence. (Typically, the buffer is written out to the * sequence verbatim.) In either case, the character @a c is also * written out, if @a c is not @c eof(). diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index 7f462a20dff..864741129a9 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -64,7 +64,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) class error_category { protected: - error_category() = default; + error_category(); public: virtual ~error_category() { } @@ -100,6 +100,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { return this != &__other; } }; + inline error_category::error_category() = default; + // DR 890. _GLIBCXX_CONST const error_category& system_category() throw (); _GLIBCXX_CONST const error_category& generic_category() throw (); diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 18cd89bca3b..1c46852a8fa 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -174,8 +174,7 @@ namespace std template<typename... _UElements> _Tuple_impl(_Tuple_impl<_Idx, _UElements...>&& __in) : _Inherited(std::move(__in._M_tail())), - _Base(std::forward<typename _Tuple_impl<_Idx, _UElements...>:: - _Base>(__in._M_head())) { } + _Base(std::move(__in._M_head())) { } _Tuple_impl& operator=(const _Tuple_impl& __in) diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index dd26bb84dbf..788edf66cff 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -57,7 +57,8 @@ namespace std { - /** @addtogroup metaprogramming + /** + * @addtogroup metaprogramming * @{ */ @@ -154,7 +155,7 @@ namespace std template<typename _Tp> struct __is_signed_helper<_Tp, true, false> - : public integral_constant<bool, _Tp(-1) < _Tp(0)> + : public integral_constant<bool, static_cast<bool>(_Tp(-1) < _Tp(0))> { }; /// is_signed @@ -240,52 +241,28 @@ namespace std { }; // Relationships between types. + template<typename _From, typename _To, + bool = (is_void<_From>::value || is_void<_To>::value + || is_function<_To>::value || is_array<_To>::value)> + struct __is_convertible_helper + { static const bool __value = (is_void<_From>::value + && is_void<_To>::value); }; + template<typename _From, typename _To> - struct __is_convertible_simple + struct __is_convertible_helper<_From, _To, false> : public __sfinae_types { private: static __one __test(_To); static __two __test(...); - static _From __makeFrom(); - + static typename add_rvalue_reference<_From>::type __makeFrom(); + public: static const bool __value = sizeof(__test(__makeFrom())) == 1; }; - template<typename _Tp> - struct __is_int_or_cref - { - typedef typename remove_reference<_Tp>::type __rr_Tp; - static const bool __value = (is_integral<_Tp>::value - || (is_integral<__rr_Tp>::value - && is_const<__rr_Tp>::value - && !is_volatile<__rr_Tp>::value)); - }; - - template<typename _From, typename _To, - bool = (is_void<_From>::value || is_void<_To>::value - || is_function<_To>::value || is_array<_To>::value - // This special case is here only to avoid warnings. - || (is_floating_point<typename - remove_reference<_From>::type>::value - && __is_int_or_cref<_To>::__value))> - struct __is_convertible_helper - { - // "An imaginary lvalue of type From...". - static const bool __value = (__is_convertible_simple<typename - add_lvalue_reference<_From>::type, - _To>::__value); - }; - - template<typename _From, typename _To> - struct __is_convertible_helper<_From, _To, true> - { static const bool __value = (is_void<_To>::value - || (__is_int_or_cref<_To>::__value - && !is_void<_From>::value)); }; - // XXX FIXME - // The C++0x specifications are different, see N2255. + // The C++0x specifications require front-end support, see N2255. /// is_convertible template<typename _From, typename _To> struct is_convertible diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 1a6d0b1b6b5..c3826eaca6b 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -58,6 +58,14 @@ #pragma GCC system_header +/** + * @defgroup utilities Utilities + * + * Components deemed generally useful. Includes pair, tuple, + * forward/move helpers, ratio, function object, metaprogramming and + * type traits, time, date, and memory functions. + */ + #include <bits/c++config.h> #include <bits/stl_relops.h> #include <bits/stl_pair.h> @@ -83,12 +91,4 @@ # include <initializer_list> #endif -/** - * @defgroup utilities Utilities - * - * Components deemed generally useful. Includes pair, tuple, - * forward/move helpers, ratio, function object, metaprogramming and - * type traits, time, date, and memory functions. - */ - #endif /* _GLIBCXX_UTILITY */ diff --git a/libstdc++-v3/include/tr1/shared_ptr.h b/libstdc++-v3/include/tr1/shared_ptr.h index 0afce01557b..ba2cacae4ed 100644 --- a/libstdc++-v3/include/tr1/shared_ptr.h +++ b/libstdc++-v3/include/tr1/shared_ptr.h @@ -57,16 +57,12 @@ namespace std { namespace tr1 { - template<typename _Ptr, typename _Deleter, _Lock_policy _Lp> class _Sp_counted_base_impl : public _Sp_counted_base<_Lp> { public: - /** - * @brief - * @pre __d(__p) must not throw. - */ + // Precondition: __d(__p) must not throw. _Sp_counted_base_impl(_Ptr __p, _Deleter __d) : _M_ptr(__p), _M_del(__d) { } @@ -346,31 +342,19 @@ namespace tr1 struct __const_cast_tag { }; struct __dynamic_cast_tag { }; - /** - * @class __shared_ptr - * - * A smart pointer with reference-counted copy semantics. - * The object pointed to is deleted when the last shared_ptr pointing to - * it is destroyed or reset. - */ + // A smart pointer with reference-counted copy semantics. The + // object pointed to is deleted when the last shared_ptr pointing to + // it is destroyed or reset. template<typename _Tp, _Lock_policy _Lp> class __shared_ptr { public: typedef _Tp element_type; - /** @brief Construct an empty %__shared_ptr. - * @post use_count()==0 && get()==0 - */ __shared_ptr() : _M_ptr(0), _M_refcount() // never throws { } - /** @brief Construct a %__shared_ptr that owns the pointer @a __p. - * @param __p A pointer that is convertible to element_type*. - * @post use_count() == 1 && get() == __p - * @throw std::bad_alloc, in which case @c delete @a __p is called. - */ template<typename _Tp1> explicit __shared_ptr(_Tp1* __p) @@ -381,19 +365,6 @@ namespace tr1 __enable_shared_from_this_helper(_M_refcount, __p, __p); } - // - // Requirements: _Deleter's copy constructor and destructor must - // not throw - // - // __shared_ptr will release __p by calling __d(__p) - // - /** @brief Construct a %__shared_ptr that owns the pointer @a __p - * and the deleter @a __d. - * @param __p A pointer. - * @param __d A deleter. - * @post use_count() == 1 && get() == __p - * @throw std::bad_alloc, in which case @a __d(__p) is called. - */ template<typename _Tp1, typename _Deleter> __shared_ptr(_Tp1* __p, _Deleter __d) : _M_ptr(__p), _M_refcount(__p, __d) @@ -405,24 +376,11 @@ namespace tr1 // generated copy constructor, assignment, destructor are fine. - /** @brief If @a __r is empty, constructs an empty %__shared_ptr; - * otherwise construct a %__shared_ptr that shares ownership - * with @a __r. - * @param __r A %__shared_ptr. - * @post get() == __r.get() && use_count() == __r.use_count() - */ template<typename _Tp1> __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) } - /** @brief Constructs a %__shared_ptr that shares ownership with @a __r - * and stores a copy of the pointer stored in @a __r. - * @param __r A weak_ptr. - * @post use_count() == __r.use_count() - * @throw bad_weak_ptr when __r.expired(), - * in which case the constructor has no effect. - */ template<typename _Tp1> explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r) @@ -435,9 +393,7 @@ namespace tr1 } #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_DEPRECATED - /** - * @post use_count() == 1 and __r.get() == 0 - */ + // Postcondition: use_count() == 1 and __r.get() == 0 template<typename _Tp1> explicit __shared_ptr(std::auto_ptr<_Tp1>& __r) @@ -595,30 +551,30 @@ namespace tr1 { __a.swap(__b); } // 2.2.3.9 shared_ptr casts - /** @warning The seemingly equivalent - * <code>shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))</code> - * will eventually result in undefined behaviour, - * attempting to delete the same object twice. + /* The seemingly equivalent + * shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get())) + * will eventually result in undefined behaviour, + * attempting to delete the same object twice. */ template<typename _Tp, typename _Tp1, _Lock_policy _Lp> inline __shared_ptr<_Tp, _Lp> static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) { return __shared_ptr<_Tp, _Lp>(__r, __static_cast_tag()); } - /** @warning The seemingly equivalent - * <code>shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))</code> - * will eventually result in undefined behaviour, - * attempting to delete the same object twice. + /* The seemingly equivalent + * shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get())) + * will eventually result in undefined behaviour, + * attempting to delete the same object twice. */ template<typename _Tp, typename _Tp1, _Lock_policy _Lp> inline __shared_ptr<_Tp, _Lp> const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) { return __shared_ptr<_Tp, _Lp>(__r, __const_cast_tag()); } - /** @warning The seemingly equivalent - * <code>shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))</code> - * will eventually result in undefined behaviour, - * attempting to delete the same object twice. + /* The seemingly equivalent + * shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get())) + * will eventually result in undefined behaviour, + * attempting to delete the same object twice. */ template<typename _Tp, typename _Tp1, _Lock_policy _Lp> inline __shared_ptr<_Tp, _Lp> @@ -825,7 +781,6 @@ namespace tr1 }; - /// shared_ptr // The actual shared_ptr, with forwarding constructors and // assignment operators. template<typename _Tp> @@ -914,7 +869,6 @@ namespace tr1 { return shared_ptr<_Tp>(__r, __dynamic_cast_tag()); } - /// weak_ptr // The actual weak_ptr, with forwarding constructors and // assignment operators. template<typename _Tp> @@ -971,7 +925,6 @@ namespace tr1 } }; - /// enable_shared_from_this template<typename _Tp> class enable_shared_from_this { @@ -1013,7 +966,6 @@ namespace tr1 mutable weak_ptr<_Tp> _M_weak_this; }; - } } diff --git a/libstdc++-v3/include/tr1_impl/boost_sp_counted_base.h b/libstdc++-v3/include/tr1_impl/boost_sp_counted_base.h index 48e601f2171..56030856dca 100644 --- a/libstdc++-v3/include/tr1_impl/boost_sp_counted_base.h +++ b/libstdc++-v3/include/tr1_impl/boost_sp_counted_base.h @@ -51,6 +51,10 @@ namespace std { _GLIBCXX_BEGIN_NAMESPACE_TR1 + /** + * @brief Exception possibly thrown by @c shared_ptr. + * @ingroup exceptions + */ class bad_weak_ptr : public std::exception { public: diff --git a/libstdc++-v3/include/tr1_impl/regex b/libstdc++-v3/include/tr1_impl/regex index 6f76a981419..8df62c212cc 100644 --- a/libstdc++-v3/include/tr1_impl/regex +++ b/libstdc++-v3/include/tr1_impl/regex @@ -135,9 +135,9 @@ namespace regex_constants * Specifies that the grammar recognized by the regular expression engine is * that used by POSIX utility awk in IEEE Std 1003.1-2001. This option is * identical to syntax_option_type extended, except that C-style escape - * sequences are supported. These sequences are, explicitly, "\\", "\a", - * "\b", "\f", "\n", "\r", "\t" , "\v", "\"", "'", - * and "\ddd" (where ddd is one, two, or three octal digits). + * sequences are supported. These sequences are, explicitly, '\\', '\a', + * '\b', '\f', '\n', '\r', '\t' , '\v', '\'', ''', + * and '\ddd' (where ddd is one, two, or three octal digits). */ static const syntax_option_type awk = 1 << _S_awk; @@ -202,26 +202,26 @@ namespace regex_constants /** * The first character in the sequence [first, last) is treated as though it - * is not at the beginning of a line, so the character "^" in the regular + * is not at the beginning of a line, so the character '^' in the regular * expression shall not match [first, first). */ static const match_flag_type match_not_bol = 1 << _S_not_bol; /** * The last character in the sequence [first, last) is treated as though it - * is not at the end of a line, so the character "$" in the regular + * is not at the end of a line, so the character '$' in the regular * expression shall not match [last, last). */ static const match_flag_type match_not_eol = 1 << _S_not_eol; /** - * The expression "\b" is not matched against the sub-sequence + * The expression '\b' is not matched against the sub-sequence * [first,first). */ static const match_flag_type match_not_bow = 1 << _S_not_bow; /** - * The expression "\b" should not be matched against the sub-sequence + * The expression '\b' should not be matched against the sub-sequence * [last,last). */ static const match_flag_type match_not_eow = 1 << _S_not_eow; @@ -363,7 +363,7 @@ namespace regex_constants static const error_type error_space(_S_error_space); /** - * One of "*?+{" was not preceded by a valid regular expression. + * One of '*?+{' was not preceded by a valid regular expression. */ static const error_type error_badrepeat(_S_error_badrepeat); @@ -2532,7 +2532,7 @@ namespace regex_constants // [7.12.2] Class template regex_token_iterator /** - * Iterates over submatches in a range (or "splits" a text string). + * Iterates over submatches in a range (or 'splits' a text string). * * The purpose of this iterator is to enumerate all, or all specified, * matches of a regular expression within a text range. The dereferenced diff --git a/libstdc++-v3/include/tr1_impl/type_traits b/libstdc++-v3/include/tr1_impl/type_traits index 75b85ea2f82..47f5e8f7e60 100644 --- a/libstdc++-v3/include/tr1_impl/type_traits +++ b/libstdc++-v3/include/tr1_impl/type_traits @@ -497,5 +497,6 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1 #undef _DEFINE_SPEC // @} group metaprogramming + _GLIBCXX_END_NAMESPACE_TR1 } |