summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/Makefile.am21
-rw-r--r--libstdc++-v3/include/Makefile.in57
-rw-r--r--libstdc++-v3/include/bits/atomic_0.h5
-rw-r--r--libstdc++-v3/include/bits/atomic_2.h5
-rw-r--r--libstdc++-v3/include/bits/basic_string.h13
-rw-r--r--libstdc++-v3/include/bits/c++config6
-rw-r--r--libstdc++-v3/include/bits/random.h144
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h1366
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h1114
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h158
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h6
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h63
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_funcs.h8
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_types.h12
-rw-r--r--libstdc++-v3/include/bits/stl_pair.h28
-rw-r--r--libstdc++-v3/include/bits/stl_tempbuf.h4
-rw-r--r--libstdc++-v3/include/bits/stream_iterator.h7
-rw-r--r--libstdc++-v3/include/bits/streambuf_iterator.h7
-rw-r--r--libstdc++-v3/include/bits/valarray_array.h31
-rw-r--r--libstdc++-v3/include/c_compatibility/stdatomic.h7
-rw-r--r--libstdc++-v3/include/c_global/cassert2
-rw-r--r--libstdc++-v3/include/c_global/cctype2
-rw-r--r--libstdc++-v3/include/c_global/cerrno2
-rw-r--r--libstdc++-v3/include/c_global/cfloat2
-rw-r--r--libstdc++-v3/include/c_global/ciso6462
-rw-r--r--libstdc++-v3/include/c_global/climits2
-rw-r--r--libstdc++-v3/include/c_global/clocale2
-rw-r--r--libstdc++-v3/include/c_global/cmath2
-rw-r--r--libstdc++-v3/include/c_global/csetjmp2
-rw-r--r--libstdc++-v3/include/c_global/csignal2
-rw-r--r--libstdc++-v3/include/c_global/cstdarg2
-rw-r--r--libstdc++-v3/include/c_global/cstdatomic2
-rw-r--r--libstdc++-v3/include/c_global/cstddef2
-rw-r--r--libstdc++-v3/include/c_global/cstdio2
-rw-r--r--libstdc++-v3/include/c_global/cstdlib2
-rw-r--r--libstdc++-v3/include/c_global/cstring2
-rw-r--r--libstdc++-v3/include/c_global/ctime2
-rw-r--r--libstdc++-v3/include/c_global/cwchar2
-rw-r--r--libstdc++-v3/include/c_global/cwctype2
-rw-r--r--libstdc++-v3/include/decimal/decimal482
-rw-r--r--libstdc++-v3/include/decimal/decimal.h466
-rw-r--r--libstdc++-v3/include/ext/bitmap_allocator.h122
-rw-r--r--libstdc++-v3/include/parallel/balanced_quicksort.h753
-rw-r--r--libstdc++-v3/include/parallel/base.h650
-rw-r--r--libstdc++-v3/include/parallel/checkers.h7
-rw-r--r--libstdc++-v3/include/parallel/compatibility.h12
-rw-r--r--libstdc++-v3/include/parallel/equally_split.h99
-rw-r--r--libstdc++-v3/include/parallel/find.h633
-rw-r--r--libstdc++-v3/include/parallel/find_selectors.h97
-rw-r--r--libstdc++-v3/include/parallel/for_each.h36
-rw-r--r--libstdc++-v3/include/parallel/for_each_selectors.h52
-rw-r--r--libstdc++-v3/include/parallel/list_partition.h25
-rw-r--r--libstdc++-v3/include/parallel/losertree.h1728
-rw-r--r--libstdc++-v3/include/parallel/merge.h102
-rw-r--r--libstdc++-v3/include/parallel/multiseq_selection.h52
-rw-r--r--libstdc++-v3/include/parallel/multiway_merge.h3811
-rw-r--r--libstdc++-v3/include/parallel/multiway_mergesort.h747
-rw-r--r--libstdc++-v3/include/parallel/numeric4
-rw-r--r--libstdc++-v3/include/parallel/omp_loop.h100
-rw-r--r--libstdc++-v3/include/parallel/omp_loop_static.h74
-rw-r--r--libstdc++-v3/include/parallel/par_loop.h160
-rw-r--r--libstdc++-v3/include/parallel/partial_sum.h283
-rw-r--r--libstdc++-v3/include/parallel/partition.h726
-rw-r--r--libstdc++-v3/include/parallel/queue.h32
-rw-r--r--libstdc++-v3/include/parallel/quicksort.h56
-rw-r--r--libstdc++-v3/include/parallel/random_number.h4
-rw-r--r--libstdc++-v3/include/parallel/random_shuffle.h844
-rw-r--r--libstdc++-v3/include/parallel/search.h194
-rw-r--r--libstdc++-v3/include/parallel/set_operations.h841
-rw-r--r--libstdc++-v3/include/parallel/sort.h120
-rw-r--r--libstdc++-v3/include/parallel/tags.h64
-rw-r--r--libstdc++-v3/include/parallel/unique_copy.h279
-rw-r--r--libstdc++-v3/include/parallel/workstealing.h435
-rw-r--r--libstdc++-v3/include/precompiled/stdc++.h1
-rw-r--r--libstdc++-v3/include/profile/impl/profiler_hashtable_size.h2
-rw-r--r--libstdc++-v3/include/profile/impl/profiler_state.h2
-rw-r--r--libstdc++-v3/include/std/chrono70
-rw-r--r--libstdc++-v3/include/std/future700
-rw-r--r--libstdc++-v3/include/std/iosfwd59
-rw-r--r--libstdc++-v3/include/std/limits16
-rw-r--r--libstdc++-v3/include/std/memory28
-rw-r--r--libstdc++-v3/include/std/ostream4
-rw-r--r--libstdc++-v3/include/std/random1
-rw-r--r--libstdc++-v3/include/std/sstream4
-rw-r--r--libstdc++-v3/include/std/streambuf28
-rw-r--r--libstdc++-v3/include/std/system_error4
-rw-r--r--libstdc++-v3/include/std/tuple3
-rw-r--r--libstdc++-v3/include/std/type_traits51
-rw-r--r--libstdc++-v3/include/std/utility16
-rw-r--r--libstdc++-v3/include/tr1/shared_ptr.h82
-rw-r--r--libstdc++-v3/include/tr1_impl/boost_sp_counted_base.h4
-rw-r--r--libstdc++-v3/include/tr1_impl/regex18
-rw-r--r--libstdc++-v3/include/tr1_impl/type_traits1
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 &gt; 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 &gt; 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 &lt;iosfwd&gt;
+ * 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 &lt;iosfwd&gt;
- * 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
}