Add parallel mode.
2007-09-11 Johannes Singler <singler@ira.uka.de> Leonor Frias Moya <lfrias@lsi.upc.edu> Felix Putze <kontakt@felix-putze.de> Marius Elvert <marius.elvert@ira.uka.de> Felix Bondarenko <f.bondarenko@web.de> Robert Geisberger <robert.geisberger@stud.uni-karlsruhe.de> Robin Dapp <r.dapp@freenet.de> Benjamin Kosnik <bkoz@redhat.com> Add parallel mode. * include/parallel: New. * include/parallel/iterator.h: New. * include/parallel/multiway_merge.h: New. * include/parallel/parallel.h: New. * include/parallel/algorithm * include/parallel/find_selectors.h: New. * include/parallel/losertree.h: New. * include/parallel/list_partition.h: New. * include/parallel/types.h: New. * include/parallel/for_each.h: New. * include/parallel/multiseq_selection.h: New. * include/parallel/workstealing.h: New. * include/parallel/base.h: New. * include/parallel/par_loop.h: New. * include/parallel/numeric * include/parallel/features.h: New. * include/parallel/quicksort.h: New. * include/parallel/algorithmfwd.h: New. * include/parallel/equally_split.h: New. * include/parallel/compiletime_settings.h: New. * include/parallel/for_each_selectors.h: New. * include/parallel/basic_iterator.h: New. * include/parallel/omp_loop_static.h: New. * include/parallel/random_shuffle.h: New. * include/parallel/balanced_quicksort.h: New. * include/parallel/set_operations.h: New. * include/parallel/tags.h: New. * include/parallel/merge.h: New. * include/parallel/tree.h: New. * include/parallel/settings.h: New. * include/parallel/unique_copy.h: New. * include/parallel/multiway_mergesort.h: New. * include/parallel/numericfwd.h: New. * include/parallel/search.h: New. * include/parallel/partition.h: New. * include/parallel/compatibility.h: New. * include/parallel/algobase.h: New. * include/parallel/find.h: New. * include/parallel/partial_sum.h: New. * include/parallel/algo.h: New. * include/parallel/omp_loop.h: New. * include/parallel/queue.h: New. * include/parallel/timing.h: New. * include/parallel/sort.h: New. * include/parallel/checkers.h: New. * include/parallel/random_number.h: New. * include/bits/algorithmfwd.h: New. * acinclude.m4 (GLIBCXX_ENABLE_PARALLEL): New. * configure.host: Add atomic_flags. * configure.ac: Export ATOMIC_FLAGS, call GLIBCXX_ENABLE_PARALLEL. * src/Makefile.am: Add parallel_list rules. * include/Makefile.am: Add parallel files. * testsuite/Makefile.am (check-parallel): Add. (check-performance-parallel): Add. * config.h.in: Regenerate. * configure: Same. * libsupc++/Makefile.in: Same. * testsuite/Makefile.in: Same. * Makefile.in: Same. * libmath/Makefile.in: Same. * include/Makefile.in: Same. * src/Makefile.in: Same. * po/Makefile.in: Same. * config/abi/pre/gnu.ver: Export parallel list bits. * docs/html/parallel_mode.html: New. * docs/html/documentation.html: Add link. * docs/doxygen/user.cfg.in: Adjust for new files and directory. * docs/doxygen/doxygroups.cc: Adjust namespace markup. * include/debug/set.h: Adjust for _GLIBCXX_STD_D or _P change. * include/debug/bitset: Same. * include/debug/multiset.h: Same. * include/debug/vector: Same. * include/debug/map.h: Same. * include/debug/deque: Same. * include/debug/list: Same. * include/debug/debug.h: Same. * include/debug/multimap.h: Same. * include/std/algorithm: Same. * include/std/numeric: Same. * include/std/bitset: Same. * include/std/string: Same. * include/ext/hash_map: Same. * include/ext/hash_set: Same. * include/bits/stl_list.h: Same. * include/bits/stl_map.h: Same. * include/bits/stl_algobase.h: Same. * include/bits/stl_set.h: Same. * include/bits/stl_multimap.h: Same. * include/bits/stl_vector.h: Same. * include/bits/stl_numeric.h: Same. * include/bits/stl_deque.h: Same. * include/bits/stl_multiset.h: Same. * include/bits/char_traits.h: Same. * include/bits/stl_algo.h: Same. * include/bits/c++config: Same. * include/bits/vector.tcc: Same. * include/bits/deque.tcc: Same. * include/bits/stl_bvector.h: Same. * include/bits/list.tcc: Same. * src/list.cc: Same. * src/parallel_list.cc: New. * testsuite/lib/libstdc++.exp (check_v3_target_parallel_mode): New. * testsuite/lib/dg-options.exp (dg-require-parallel-mode): New. * scripts/testsuite_flags.in (--cxxparallelflags): New. * scripts/check_performance: Adjust. * testsuite/25_algorithms/headers/parallel_algorithm.cc: New. * testsuite/25_algorithms/headers/algorithm_parallel_mode.cc: New. * testsuite/25_algorithms/headers/parallel_algorithm_mixed1.cc: New. * testsuite/25_algorithms/headers/parallel_algorithm_mixed2.cc: New. * testsuite/26_numerics/headers/numeric/parallel_numeric.cc: New. * testsuite/26_numerics/headers/numeric/numeric_parallel_mode.cc: New. * testsuite/26_numerics/headers/numeric/ parallel_numeric_mixed1.cc: New. * testsuite/26_numerics/headers/numeric/ parallel_numeric_mixed2.cc: New. Co-Authored-By: Benjamin Kosnik <bkoz@redhat.com> Co-Authored-By: Felix Bondarenko <f.bondarenko@web.de> Co-Authored-By: Felix Putze <kontakt@felix-putze.de> Co-Authored-By: Leonor Frias Moya <lfrias@lsi.upc.edu> Co-Authored-By: Marius Elvert <marius.elvert@ira.uka.de> Co-Authored-By: Robert Geisberger <robert.geisberger@stud.uni-karlsruhe.de> Co-Authored-By: Robin Dapp <r.dapp@freenet.de> From-SVN: r128395
This commit is contained in:
parent
f6ee8d7b73
commit
c2ba97097b
@ -1,3 +1,134 @@
|
||||
2007-09-11 Johannes Singler <singler@ira.uka.de>
|
||||
Leonor Frias Moya <lfrias@lsi.upc.edu>
|
||||
Felix Putze <kontakt@felix-putze.de>
|
||||
Marius Elvert <marius.elvert@ira.uka.de>
|
||||
Felix Bondarenko <f.bondarenko@web.de>
|
||||
Robert Geisberger <robert.geisberger@stud.uni-karlsruhe.de>
|
||||
Robin Dapp <r.dapp@freenet.de>
|
||||
Benjamin Kosnik <bkoz@redhat.com>
|
||||
|
||||
Add parallel mode.
|
||||
* include/parallel: New.
|
||||
* include/parallel/iterator.h: New.
|
||||
* include/parallel/multiway_merge.h: New.
|
||||
* include/parallel/parallel.h: New.
|
||||
* include/parallel/algorithm
|
||||
* include/parallel/find_selectors.h: New.
|
||||
* include/parallel/losertree.h: New.
|
||||
* include/parallel/list_partition.h: New.
|
||||
* include/parallel/types.h: New.
|
||||
* include/parallel/for_each.h: New.
|
||||
* include/parallel/multiseq_selection.h: New.
|
||||
* include/parallel/workstealing.h: New.
|
||||
* include/parallel/base.h: New.
|
||||
* include/parallel/par_loop.h: New.
|
||||
* include/parallel/numeric
|
||||
* include/parallel/features.h: New.
|
||||
* include/parallel/quicksort.h: New.
|
||||
* include/parallel/algorithmfwd.h: New.
|
||||
* include/parallel/equally_split.h: New.
|
||||
* include/parallel/compiletime_settings.h: New.
|
||||
* include/parallel/for_each_selectors.h: New.
|
||||
* include/parallel/basic_iterator.h: New.
|
||||
* include/parallel/omp_loop_static.h: New.
|
||||
* include/parallel/random_shuffle.h: New.
|
||||
* include/parallel/balanced_quicksort.h: New.
|
||||
* include/parallel/set_operations.h: New.
|
||||
* include/parallel/tags.h: New.
|
||||
* include/parallel/merge.h: New.
|
||||
* include/parallel/tree.h: New.
|
||||
* include/parallel/settings.h: New.
|
||||
* include/parallel/unique_copy.h: New.
|
||||
* include/parallel/multiway_mergesort.h: New.
|
||||
* include/parallel/numericfwd.h: New.
|
||||
* include/parallel/search.h: New.
|
||||
* include/parallel/partition.h: New.
|
||||
* include/parallel/compatibility.h: New.
|
||||
* include/parallel/algobase.h: New.
|
||||
* include/parallel/find.h: New.
|
||||
* include/parallel/partial_sum.h: New.
|
||||
* include/parallel/algo.h: New.
|
||||
* include/parallel/omp_loop.h: New.
|
||||
* include/parallel/queue.h: New.
|
||||
* include/parallel/timing.h: New.
|
||||
* include/parallel/sort.h: New.
|
||||
* include/parallel/checkers.h: New.
|
||||
* include/parallel/random_number.h: New.
|
||||
* include/bits/algorithmfwd.h: New.
|
||||
|
||||
* acinclude.m4 (GLIBCXX_ENABLE_PARALLEL): New.
|
||||
* configure.host: Add atomic_flags.
|
||||
* configure.ac: Export ATOMIC_FLAGS, call GLIBCXX_ENABLE_PARALLEL.
|
||||
* src/Makefile.am: Add parallel_list rules.
|
||||
* include/Makefile.am: Add parallel files.
|
||||
* testsuite/Makefile.am (check-parallel): Add.
|
||||
(check-performance-parallel): Add.
|
||||
* config.h.in: Regenerate.
|
||||
* configure: Same.
|
||||
* libsupc++/Makefile.in: Same.
|
||||
* testsuite/Makefile.in: Same.
|
||||
* Makefile.in: Same.
|
||||
* libmath/Makefile.in: Same.
|
||||
* include/Makefile.in: Same.
|
||||
* src/Makefile.in: Same.
|
||||
* po/Makefile.in: Same.
|
||||
|
||||
* config/abi/pre/gnu.ver: Export parallel list bits.
|
||||
|
||||
* docs/html/parallel_mode.html: New.
|
||||
* docs/html/documentation.html: Add link.
|
||||
* docs/doxygen/user.cfg.in: Adjust for new files and directory.
|
||||
* docs/doxygen/doxygroups.cc: Adjust namespace markup.
|
||||
|
||||
* include/debug/set.h: Adjust for _GLIBCXX_STD_D or _P change.
|
||||
* include/debug/bitset: Same.
|
||||
* include/debug/multiset.h: Same.
|
||||
* include/debug/vector: Same.
|
||||
* include/debug/map.h: Same.
|
||||
* include/debug/deque: Same.
|
||||
* include/debug/list: Same.
|
||||
* include/debug/debug.h: Same.
|
||||
* include/debug/multimap.h: Same.
|
||||
* include/std/algorithm: Same.
|
||||
* include/std/numeric: Same.
|
||||
* include/std/bitset: Same.
|
||||
* include/std/string: Same.
|
||||
* include/ext/hash_map: Same.
|
||||
* include/ext/hash_set: Same.
|
||||
* include/bits/stl_list.h: Same.
|
||||
* include/bits/stl_map.h: Same.
|
||||
* include/bits/stl_algobase.h: Same.
|
||||
* include/bits/stl_set.h: Same.
|
||||
* include/bits/stl_multimap.h: Same.
|
||||
* include/bits/stl_vector.h: Same.
|
||||
* include/bits/stl_numeric.h: Same.
|
||||
* include/bits/stl_deque.h: Same.
|
||||
* include/bits/stl_multiset.h: Same.
|
||||
* include/bits/char_traits.h: Same.
|
||||
* include/bits/stl_algo.h: Same.
|
||||
* include/bits/c++config: Same.
|
||||
* include/bits/vector.tcc: Same.
|
||||
* include/bits/deque.tcc: Same.
|
||||
* include/bits/stl_bvector.h: Same.
|
||||
* include/bits/list.tcc: Same.
|
||||
* src/list.cc: Same.
|
||||
* src/parallel_list.cc: New.
|
||||
|
||||
* testsuite/lib/libstdc++.exp (check_v3_target_parallel_mode): New.
|
||||
* testsuite/lib/dg-options.exp (dg-require-parallel-mode): New.
|
||||
* scripts/testsuite_flags.in (--cxxparallelflags): New.
|
||||
* scripts/check_performance: Adjust.
|
||||
* testsuite/25_algorithms/headers/parallel_algorithm.cc: New.
|
||||
* testsuite/25_algorithms/headers/algorithm_parallel_mode.cc: New.
|
||||
* testsuite/25_algorithms/headers/parallel_algorithm_mixed1.cc: New.
|
||||
* testsuite/25_algorithms/headers/parallel_algorithm_mixed2.cc: New.
|
||||
* testsuite/26_numerics/headers/numeric/parallel_numeric.cc: New.
|
||||
* testsuite/26_numerics/headers/numeric/numeric_parallel_mode.cc: New.
|
||||
* testsuite/26_numerics/headers/numeric/
|
||||
parallel_numeric_mixed1.cc: New.
|
||||
* testsuite/26_numerics/headers/numeric/
|
||||
parallel_numeric_mixed2.cc: New.
|
||||
|
||||
2007-09-11 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* testsuite/lib/libstdc++.exp (libstdc++_init): Revert part of
|
||||
|
@ -103,6 +103,7 @@ AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@
|
||||
ATOMIC_FLAGS = @ATOMIC_FLAGS@
|
||||
ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
@ -140,6 +141,8 @@ ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_PARALLEL_FALSE = @ENABLE_PARALLEL_FALSE@
|
||||
ENABLE_PARALLEL_TRUE = @ENABLE_PARALLEL_TRUE@
|
||||
ENABLE_SYMVERS_DARWIN_FALSE = @ENABLE_SYMVERS_DARWIN_FALSE@
|
||||
ENABLE_SYMVERS_DARWIN_TRUE = @ENABLE_SYMVERS_DARWIN_TRUE@
|
||||
ENABLE_SYMVERS_FALSE = @ENABLE_SYMVERS_FALSE@
|
||||
|
@ -1725,6 +1725,23 @@ AC_DEFUN([GLIBCXX_ENABLE_CONCEPT_CHECKS], [
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check for parallel mode pre-requisites, including OpenMP support.
|
||||
dnl
|
||||
dnl + Usage: GLIBCXX_ENABLE_PARALLEL
|
||||
dnl
|
||||
AC_DEFUN([GLIBCXX_ENABLE_PARALLEL], [
|
||||
|
||||
enable_parallel=no;
|
||||
if test -f "${glibcxx_builddir}/../libgomp/omp.h"; then
|
||||
enable_parallel=yes;
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for parallel mode support])
|
||||
AC_MSG_RESULT([$enable_parallel])
|
||||
GLIBCXX_CONDITIONAL(ENABLE_PARALLEL, test $enable_parallel = yes)
|
||||
])
|
||||
|
||||
|
||||
dnl
|
||||
dnl Check for which I/O library to use: stdio, or something specific.
|
||||
@ -2072,7 +2089,7 @@ AC_DEFUN([GLIBCXX_ENABLE_PCH], [
|
||||
|
||||
GLIBCXX_CONDITIONAL(GLIBCXX_BUILD_PCH, test $enable_libstdcxx_pch = yes)
|
||||
if test $enable_libstdcxx_pch = yes; then
|
||||
glibcxx_PCHFLAGS="-include bits/stdtr1c++.h"
|
||||
glibcxx_PCHFLAGS="-include bits/stdc++.h"
|
||||
else
|
||||
glibcxx_PCHFLAGS=""
|
||||
fi
|
||||
|
@ -63,6 +63,9 @@
|
||||
/* Define if EBADMSG exists. */
|
||||
#undef HAVE_EBADMSG
|
||||
|
||||
/* Define if ECANCELED exists. */
|
||||
#undef HAVE_ECANCELED
|
||||
|
||||
/* Define to 1 if you have the <endian.h> header file. */
|
||||
#undef HAVE_ENDIAN_H
|
||||
|
||||
|
@ -770,6 +770,13 @@ GLIBCXX_3.4.10 {
|
||||
_ZNKSt4hashISsEclESs;
|
||||
_ZNKSt4hashISt10error_codeEclES0_;
|
||||
|
||||
# for parallel mode
|
||||
_ZNSt9__cxx199815_List_node_base4hook*;
|
||||
_ZNSt9__cxx199815_List_node_base4swap*;
|
||||
_ZNSt9__cxx199815_List_node_base6unhookEv;
|
||||
_ZNSt9__cxx199815_List_node_base7reverseEv;
|
||||
_ZNSt9__cxx199815_List_node_base8transfer*;
|
||||
|
||||
} GLIBCXX_3.4.9;
|
||||
|
||||
# Symbols in the support library (libsupc++) have their own tag.
|
||||
|
42
libstdc++-v3/configure
vendored
42
libstdc++-v3/configure
vendored
@ -458,7 +458,7 @@ ac_includes_default="\
|
||||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS libtool_VERSION multi_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar glibcxx_builddir glibcxx_srcdir toplevel_srcdir CC ac_ct_CC EXEEXT OBJEXT CXX ac_ct_CXX CFLAGS CXXFLAGS LN_S AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CPP CPPFLAGS EGREP LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM lt_ECHO LDFLAGS CXXCPP enable_shared enable_static GLIBCXX_HOSTED_TRUE GLIBCXX_HOSTED_FALSE GLIBCXX_BUILD_PCH_TRUE GLIBCXX_BUILD_PCH_FALSE glibcxx_PCHFLAGS CSTDIO_H BASIC_FILE_H BASIC_FILE_CC check_msgfmt glibcxx_MOFILES glibcxx_POFILES glibcxx_localedir USE_NLS CLOCALE_H CMESSAGES_H CCODECVT_CC CCOLLATE_CC CCTYPE_CC CMESSAGES_CC CMONEY_CC CNUMERIC_CC CTIME_H CTIME_CC CLOCALE_CC CLOCALE_INTERNAL_H ALLOCATOR_H ALLOCATOR_NAME C_INCLUDE_DIR GLIBCXX_C_HEADERS_C_TRUE GLIBCXX_C_HEADERS_C_FALSE GLIBCXX_C_HEADERS_C_STD_TRUE GLIBCXX_C_HEADERS_C_STD_FALSE GLIBCXX_C_HEADERS_C_GLOBAL_TRUE GLIBCXX_C_HEADERS_C_GLOBAL_FALSE GLIBCXX_C_HEADERS_COMPATIBILITY_TRUE GLIBCXX_C_HEADERS_COMPATIBILITY_FALSE GLIBCXX_C_HEADERS_EXTRA_TRUE GLIBCXX_C_HEADERS_EXTRA_FALSE DEBUG_FLAGS GLIBCXX_BUILD_DEBUG_TRUE GLIBCXX_BUILD_DEBUG_FALSE EXTRA_CXX_FLAGS glibcxx_thread_h WERROR SECTION_FLAGS SECTION_LDFLAGS OPT_LDFLAGS LIBMATHOBJS LIBICONV LTLIBICONV SYMVER_FILE port_specific_symbol_files ENABLE_SYMVERS_TRUE ENABLE_SYMVERS_FALSE ENABLE_SYMVERS_GNU_TRUE ENABLE_SYMVERS_GNU_FALSE ENABLE_SYMVERS_GNU_NAMESPACE_TRUE ENABLE_SYMVERS_GNU_NAMESPACE_FALSE ENABLE_SYMVERS_DARWIN_TRUE ENABLE_SYMVERS_DARWIN_FALSE ENABLE_VISIBILITY_TRUE ENABLE_VISIBILITY_FALSE GLIBCXX_LDBL_COMPAT_TRUE GLIBCXX_LDBL_COMPAT_FALSE baseline_dir ATOMICITY_SRCDIR ATOMIC_WORD_SRCDIR CPU_DEFINES_SRCDIR ABI_TWEAKS_SRCDIR OS_INC_SRCDIR ERROR_CONSTANTS_SRCDIR glibcxx_prefixdir gxx_include_dir glibcxx_toolexecdir glibcxx_toolexeclibdir GLIBCXX_INCLUDES TOPLEVEL_INCLUDES OPTIMIZE_CXXFLAGS WARN_FLAGS LIBSUPCXX_PICFLAGS LIBOBJS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS libtool_VERSION multi_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar glibcxx_builddir glibcxx_srcdir toplevel_srcdir CC ac_ct_CC EXEEXT OBJEXT CXX ac_ct_CXX CFLAGS CXXFLAGS LN_S AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CPP CPPFLAGS EGREP LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM lt_ECHO LDFLAGS CXXCPP enable_shared enable_static GLIBCXX_HOSTED_TRUE GLIBCXX_HOSTED_FALSE GLIBCXX_BUILD_PCH_TRUE GLIBCXX_BUILD_PCH_FALSE glibcxx_PCHFLAGS CSTDIO_H BASIC_FILE_H BASIC_FILE_CC check_msgfmt glibcxx_MOFILES glibcxx_POFILES glibcxx_localedir USE_NLS CLOCALE_H CMESSAGES_H CCODECVT_CC CCOLLATE_CC CCTYPE_CC CMESSAGES_CC CMONEY_CC CNUMERIC_CC CTIME_H CTIME_CC CLOCALE_CC CLOCALE_INTERNAL_H ALLOCATOR_H ALLOCATOR_NAME C_INCLUDE_DIR GLIBCXX_C_HEADERS_C_TRUE GLIBCXX_C_HEADERS_C_FALSE GLIBCXX_C_HEADERS_C_STD_TRUE GLIBCXX_C_HEADERS_C_STD_FALSE GLIBCXX_C_HEADERS_C_GLOBAL_TRUE GLIBCXX_C_HEADERS_C_GLOBAL_FALSE GLIBCXX_C_HEADERS_COMPATIBILITY_TRUE GLIBCXX_C_HEADERS_COMPATIBILITY_FALSE GLIBCXX_C_HEADERS_EXTRA_TRUE GLIBCXX_C_HEADERS_EXTRA_FALSE DEBUG_FLAGS GLIBCXX_BUILD_DEBUG_TRUE GLIBCXX_BUILD_DEBUG_FALSE ENABLE_PARALLEL_TRUE ENABLE_PARALLEL_FALSE EXTRA_CXX_FLAGS glibcxx_thread_h WERROR SECTION_FLAGS SECTION_LDFLAGS OPT_LDFLAGS LIBMATHOBJS LIBICONV LTLIBICONV SYMVER_FILE port_specific_symbol_files ENABLE_SYMVERS_TRUE ENABLE_SYMVERS_FALSE ENABLE_SYMVERS_GNU_TRUE ENABLE_SYMVERS_GNU_FALSE ENABLE_SYMVERS_GNU_NAMESPACE_TRUE ENABLE_SYMVERS_GNU_NAMESPACE_FALSE ENABLE_SYMVERS_DARWIN_TRUE ENABLE_SYMVERS_DARWIN_FALSE ENABLE_VISIBILITY_TRUE ENABLE_VISIBILITY_FALSE GLIBCXX_LDBL_COMPAT_TRUE GLIBCXX_LDBL_COMPAT_FALSE baseline_dir ATOMICITY_SRCDIR ATOMIC_WORD_SRCDIR ATOMIC_FLAGS CPU_DEFINES_SRCDIR ABI_TWEAKS_SRCDIR OS_INC_SRCDIR ERROR_CONSTANTS_SRCDIR glibcxx_prefixdir gxx_include_dir glibcxx_toolexecdir glibcxx_toolexeclibdir GLIBCXX_INCLUDES TOPLEVEL_INCLUDES OPTIMIZE_CXXFLAGS WARN_FLAGS LIBSUPCXX_PICFLAGS LIBOBJS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@ -13949,7 +13949,7 @@ echo "${ECHO_T}$enable_libstdcxx_pch" >&6
|
||||
|
||||
|
||||
if test $enable_libstdcxx_pch = yes; then
|
||||
glibcxx_PCHFLAGS="-include bits/stdtr1c++.h"
|
||||
glibcxx_PCHFLAGS="-include bits/stdc++.h"
|
||||
else
|
||||
glibcxx_PCHFLAGS=""
|
||||
fi
|
||||
@ -16468,6 +16468,19 @@ fi;
|
||||
echo "${ECHO_T}$enable_libstdcxx_debug" >&6
|
||||
|
||||
|
||||
|
||||
|
||||
enable_parallel=no;
|
||||
if test -f "${glibcxx_builddir}/../libgomp/omp.h"; then
|
||||
enable_parallel=yes;
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: checking for parallel mode support" >&5
|
||||
echo $ECHO_N "checking for parallel mode support... $ECHO_C" >&6
|
||||
echo "$as_me:$LINENO: result: $enable_parallel" >&5
|
||||
echo "${ECHO_T}$enable_parallel" >&6
|
||||
|
||||
|
||||
echo "$as_me:$LINENO: checking for extra compiler flags for building" >&5
|
||||
echo $ECHO_N "checking for extra compiler flags for building... $ECHO_C" >&6
|
||||
# Check whether --enable-cxx-flags or --disable-cxx-flags was given.
|
||||
@ -17279,7 +17292,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
# Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style.
|
||||
cat > conftest.$ac_ext << EOF
|
||||
#line 17282 "configure"
|
||||
#line 17295 "configure"
|
||||
int main()
|
||||
{
|
||||
// NB: _Atomic_word not necessarily int.
|
||||
@ -93897,6 +93910,7 @@ done
|
||||
# Propagate the target-specific source directories through the build chain.
|
||||
ATOMICITY_SRCDIR=config/${atomicity_dir}
|
||||
ATOMIC_WORD_SRCDIR=config/${atomic_word_dir}
|
||||
ATOMIC_FLAGS=${atomic_flags}
|
||||
CPU_DEFINES_SRCDIR=config/${cpu_defines_dir}
|
||||
OS_INC_SRCDIR=config/${os_include_dir}
|
||||
ERROR_CONSTANTS_SRCDIR=config/${error_constants_dir}
|
||||
@ -93909,6 +93923,7 @@ ABI_TWEAKS_SRCDIR=config/${abi_tweaks_dir}
|
||||
|
||||
|
||||
|
||||
|
||||
# Determine cross-compile flags and AM_CONDITIONALs.
|
||||
#AC_SUBST(GLIBCXX_IS_NATIVE)
|
||||
#AM_CONDITIONAL(CANADIAN, test $CANADIAN = yes)
|
||||
@ -94004,6 +94019,17 @@ fi
|
||||
|
||||
|
||||
|
||||
if test $enable_parallel = yes; then
|
||||
ENABLE_PARALLEL_TRUE=
|
||||
ENABLE_PARALLEL_FALSE='#'
|
||||
else
|
||||
ENABLE_PARALLEL_TRUE='#'
|
||||
ENABLE_PARALLEL_FALSE=
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
if test $enable_symvers != no; then
|
||||
ENABLE_SYMVERS_TRUE=
|
||||
ENABLE_SYMVERS_FALSE='#'
|
||||
@ -94429,6 +94455,13 @@ echo "$as_me: error: conditional \"GLIBCXX_BUILD_DEBUG\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
if test -z "${ENABLE_PARALLEL_TRUE}" && test -z "${ENABLE_PARALLEL_FALSE}"; then
|
||||
{ { echo "$as_me:$LINENO: error: conditional \"ENABLE_PARALLEL\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." >&5
|
||||
echo "$as_me: error: conditional \"ENABLE_PARALLEL\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
if test -z "${ENABLE_SYMVERS_TRUE}" && test -z "${ENABLE_SYMVERS_FALSE}"; then
|
||||
{ { echo "$as_me:$LINENO: error: conditional \"ENABLE_SYMVERS\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." >&5
|
||||
@ -95474,6 +95507,8 @@ s,@GLIBCXX_C_HEADERS_EXTRA_FALSE@,$GLIBCXX_C_HEADERS_EXTRA_FALSE,;t t
|
||||
s,@DEBUG_FLAGS@,$DEBUG_FLAGS,;t t
|
||||
s,@GLIBCXX_BUILD_DEBUG_TRUE@,$GLIBCXX_BUILD_DEBUG_TRUE,;t t
|
||||
s,@GLIBCXX_BUILD_DEBUG_FALSE@,$GLIBCXX_BUILD_DEBUG_FALSE,;t t
|
||||
s,@ENABLE_PARALLEL_TRUE@,$ENABLE_PARALLEL_TRUE,;t t
|
||||
s,@ENABLE_PARALLEL_FALSE@,$ENABLE_PARALLEL_FALSE,;t t
|
||||
s,@EXTRA_CXX_FLAGS@,$EXTRA_CXX_FLAGS,;t t
|
||||
s,@glibcxx_thread_h@,$glibcxx_thread_h,;t t
|
||||
s,@WERROR@,$WERROR,;t t
|
||||
@ -95500,6 +95535,7 @@ s,@GLIBCXX_LDBL_COMPAT_FALSE@,$GLIBCXX_LDBL_COMPAT_FALSE,;t t
|
||||
s,@baseline_dir@,$baseline_dir,;t t
|
||||
s,@ATOMICITY_SRCDIR@,$ATOMICITY_SRCDIR,;t t
|
||||
s,@ATOMIC_WORD_SRCDIR@,$ATOMIC_WORD_SRCDIR,;t t
|
||||
s,@ATOMIC_FLAGS@,$ATOMIC_FLAGS,;t t
|
||||
s,@CPU_DEFINES_SRCDIR@,$CPU_DEFINES_SRCDIR,;t t
|
||||
s,@ABI_TWEAKS_SRCDIR@,$ABI_TWEAKS_SRCDIR,;t t
|
||||
s,@OS_INC_SRCDIR@,$OS_INC_SRCDIR,;t t
|
||||
|
@ -107,6 +107,7 @@ GLIBCXX_ENABLE_C99([yes])
|
||||
GLIBCXX_ENABLE_CONCEPT_CHECKS([no])
|
||||
GLIBCXX_ENABLE_DEBUG_FLAGS(["-g3 -O0"])
|
||||
GLIBCXX_ENABLE_DEBUG([no])
|
||||
GLIBCXX_ENABLE_PARALLEL
|
||||
GLIBCXX_ENABLE_CXX_FLAGS
|
||||
GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING([no])
|
||||
|
||||
@ -327,12 +328,14 @@ GLIBCXX_CONFIGURE_TESTSUITE
|
||||
# Propagate the target-specific source directories through the build chain.
|
||||
ATOMICITY_SRCDIR=config/${atomicity_dir}
|
||||
ATOMIC_WORD_SRCDIR=config/${atomic_word_dir}
|
||||
ATOMIC_FLAGS=${atomic_flags}
|
||||
CPU_DEFINES_SRCDIR=config/${cpu_defines_dir}
|
||||
OS_INC_SRCDIR=config/${os_include_dir}
|
||||
ERROR_CONSTANTS_SRCDIR=config/${error_constants_dir}
|
||||
ABI_TWEAKS_SRCDIR=config/${abi_tweaks_dir}
|
||||
AC_SUBST(ATOMICITY_SRCDIR)
|
||||
AC_SUBST(ATOMIC_WORD_SRCDIR)
|
||||
AC_SUBST(ATOMIC_FLAGS)
|
||||
AC_SUBST(CPU_DEFINES_SRCDIR)
|
||||
AC_SUBST(ABI_TWEAKS_SRCDIR)
|
||||
AC_SUBST(OS_INC_SRCDIR)
|
||||
|
@ -39,6 +39,9 @@
|
||||
# atomic_word_dir location of atomic_word.h
|
||||
# defaults to generic.
|
||||
#
|
||||
# atomic_flags extra flags to pass to use atomic instructions
|
||||
# defaults to nothing.
|
||||
#
|
||||
# cpu_defines_dir location of cpu_defines.h
|
||||
# defaults to generic.
|
||||
#
|
||||
@ -71,6 +74,7 @@
|
||||
c_model=c_global
|
||||
c_compatibility=no
|
||||
atomic_word_dir=cpu/generic
|
||||
atomic_flags=""
|
||||
atomicity_dir="cpu/generic"
|
||||
cpu_defines_dir="cpu/generic"
|
||||
try_cpu=generic
|
||||
@ -130,7 +134,8 @@ case "${host_cpu}" in
|
||||
esac
|
||||
|
||||
|
||||
# Set specific CPU overrides for atomic_word_dir. Most can just use generic.
|
||||
# Set specific CPU overrides for atomic_word_dir and atomic_flags.
|
||||
# Most can just use generic.
|
||||
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
|
||||
case "${host_cpu}" in
|
||||
alpha*)
|
||||
@ -142,11 +147,15 @@ case "${host_cpu}" in
|
||||
ia64)
|
||||
atomic_word_dir=cpu/ia64
|
||||
;;
|
||||
i[567]86 | x86_64)
|
||||
atomic_flags="-march=native"
|
||||
;;
|
||||
powerpc* | rs6000)
|
||||
atomic_word_dir=cpu/powerpc
|
||||
;;
|
||||
sparc* | ultrasparc)
|
||||
atomic_word_dir=cpu/sparc
|
||||
atomic_flags="-mcpu=v9"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
* export. Used only when anonymous namespaces cannot be substituted.
|
||||
*/
|
||||
/** @namespace __gnu_debug
|
||||
* @brief GNU debug mode classes for public use.
|
||||
* @brief GNU debug classes for public use.
|
||||
*/
|
||||
// // // // // // // // // // // // // // // // // // // // // // // //
|
||||
/** @addtogroup SGIextensions STL extensions from SGI
|
||||
|
@ -478,6 +478,7 @@ INPUT = @srcdir@/docs/doxygen/doxygroups.cc \
|
||||
include/@host_alias@/bits \
|
||||
include/bits \
|
||||
include/debug \
|
||||
include/parallel \
|
||||
include/ext \
|
||||
include/tr1 \
|
||||
include/tr1_impl \
|
||||
@ -562,6 +563,8 @@ INPUT = @srcdir@/docs/doxygen/doxygroups.cc \
|
||||
include/ext/slist \
|
||||
include/ext/pb_ds \
|
||||
include/ext/pb_ds/detail \
|
||||
include/parallel/algorithm \
|
||||
include/parallel/numeric \
|
||||
include/tr1/array \
|
||||
include/tr1/ccomplex \
|
||||
include/tr1/cctype \
|
||||
|
@ -222,13 +222,15 @@
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Extensions to the Standard Library
|
||||
<li>Extensions
|
||||
<ul>
|
||||
<li><a href="ext/howto.html#4">Compile-time checks</a></li>
|
||||
<li><a href="debug_mode.html">Debug mode</a></li>
|
||||
<li><a href="parallel_mode.html">Parallel mode</a></li>
|
||||
<li><a href="ext/pb_ds/index.html">Policy Based Data Structures</a></li>
|
||||
<li><a href="ext/howto.html#1">Ropes and trees and hashes, oh my!</a></li>
|
||||
<li><a href="ext/howto.html#2">Added members and types</a></li>
|
||||
<li><a href="ext/mt_allocator.html"><code>__mt_alloc</code> </a></li>
|
||||
<li><a href="ext/howto.html#4">Compile-time checks</a></li>
|
||||
<li><a href="ext/howto.html#5">LWG Issues</a></li>
|
||||
<li><a href="ext/../18_support/howto.html#6">Demangling</a></li>
|
||||
</ul>
|
||||
|
457
libstdc++-v3/docs/html/parallel_mode.html
Normal file
457
libstdc++-v3/docs/html/parallel_mode.html
Normal file
@ -0,0 +1,457 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta name="AUTHOR" content="bkoz@gcc.gnu.org (Benjamin Kosnik)" />
|
||||
<meta name="KEYWORDS" content="c++, libstdc++, gdb, g++, debug" />
|
||||
<meta name="DESCRIPTION" content="The libstdc++ parallel mode." />
|
||||
<meta name="GENERATOR" content="emacs and ten fingers" />
|
||||
<title>The libstdc++ parallel mode</title>
|
||||
<link rel="StyleSheet" href="lib3styles.css" type="text/css" />
|
||||
<link rel="Copyright" href="17_intro/license.html" type="text/html" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1 class="centered"><a name="top">The libstdc++ parallel mode</a></h1>
|
||||
|
||||
<p class="fineprint"><em>
|
||||
The latest version of this document is always available at
|
||||
<a href="http://gcc.gnu.org/onlinedocs/libstdc++/parallel_mode.html">
|
||||
http://gcc.gnu.org/onlinedocs/libstdc++/parallel_mode.html</a>.
|
||||
</em></p>
|
||||
|
||||
<p><em>
|
||||
To the <a href="http://gcc.gnu.org/libstdc++/">libstdc++-v3 homepage</a>.
|
||||
</em></p>
|
||||
|
||||
<!-- ####################################################### -->
|
||||
<hr />
|
||||
<p> The libstdc++ parallel mode is an experimental parallel
|
||||
implementation of many algorithms the C++ Standard Library.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Several of the standard algorithms, for instance
|
||||
<code>std::search</code>, are made parallel using OpenMP
|
||||
annotations. These parallel mode constructs and can be invoked by
|
||||
explicit source declaration or by compiling existing sources with a
|
||||
specific compiler flag.
|
||||
</p>
|
||||
|
||||
<h3 class="left"><a name="parallel">The libstdc++ parallel mode</a></h3>
|
||||
|
||||
<p>The libstdc++ parallel mode performs parallization of algorithms,
|
||||
function objects, classes, and functions in the C++ Standard.</p>
|
||||
|
||||
<h4 class="left">Using the libstdc++ parallel mode</h4>
|
||||
|
||||
<p>To use the libstdc++ parallel mode, compile your application with
|
||||
the compiler flag <code>-D_GLIBCXX_PARALLEL -fopenmp</code>. This
|
||||
will link in <code>libgomp</code>, the GNU OpenMP <a
|
||||
href="http://gcc.gnu.org/onlinedocs/libgomp">implementation</a>,
|
||||
whose presence is mandatory. In addition, hardware capable of atomic
|
||||
operations is de rigueur. Actually activating these atomic
|
||||
operations may require explicit compiler flags on some targets
|
||||
(like sparc and x86), such as <code>-march=i686</code>,
|
||||
<code>-march=native</code> or <code>-mcpu=v9</code>.
|
||||
</p>
|
||||
|
||||
<p>Note that the <code>_GLIBCXX_PARALLEL</code> define may change the
|
||||
sizes and behavior of standard class templates such as
|
||||
<code>std::search</code>, and therefore one can only link code
|
||||
compiled with parallel mode and code compiled without parallel mode
|
||||
if no instantiation of a container is passed between the two
|
||||
translation units. Parallel mode functionality has distinct linkage,
|
||||
and cannot be confused with normal mode symbols.</p>
|
||||
|
||||
|
||||
<p>The following library components in the include
|
||||
<code><numeric></code> are included in the parallel mode:</p>
|
||||
<ul>
|
||||
<li><code>std::accumulate</code></li>
|
||||
<li><code>std::adjacent_difference</code></li>
|
||||
<li><code>std::inner_product</code></li>
|
||||
<li><code>std::partial_sum</code></li>
|
||||
</ul>
|
||||
|
||||
<p>The following library components in the include
|
||||
<code><algorithm></code> are included in the parallel mode:</p>
|
||||
<ul>
|
||||
<li><code>std::adjacent_find</code></li>
|
||||
<li><code>std::count</code></li>
|
||||
<li><code>std::count_if</code></li>
|
||||
<li><code>std::equal</code></li>
|
||||
<li><code>std::find</code></li>
|
||||
<li><code>std::find_if</code></li>
|
||||
<li><code>std::find_first_of</code></li>
|
||||
<li><code>std::for_each</code></li>
|
||||
<li><code>std::generate</code></li>
|
||||
<li><code>std::generate_n</code></li>
|
||||
<li><code>std::lexicographical_compare</code></li>
|
||||
<li><code>std::mismatch</code></li>
|
||||
<li><code>std::search</code></li>
|
||||
<li><code>std::search_n</code></li>
|
||||
<li><code>std::transform</code></li>
|
||||
<li><code>std::replace</code></li>
|
||||
<li><code>std::replace_if</code></li>
|
||||
<li><code>std::max_element</code></li>
|
||||
<li><code>std::merge</code></li>
|
||||
<li><code>std::min_element</code></li>
|
||||
<li><code>std::nth_element</code></li>
|
||||
<li><code>std::partial_sort</code></li>
|
||||
<li><code>std::partition</code></li>
|
||||
<li><code>std::random_shuffle</code></li>
|
||||
<li><code>std::set_union</code></li>
|
||||
<li><code>std::set_intersection</code></li>
|
||||
<li><code>std::set_symmetric_difference</code></li>
|
||||
<li><code>std::set_difference</code></li>
|
||||
<li><code>std::sort</code></li>
|
||||
<li><code>std::stable_sort</code></li>
|
||||
<li><code>std::unique_copy</code></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h4 class="left">Using the parallel algorithms without parallel mode</h4>
|
||||
|
||||
<p>When it is not feasible to recompile your entire application, or
|
||||
only specific algorithms need to be parallel-aware, individual
|
||||
parallel algorithms can be made available explicitly. These
|
||||
parallel algorithms are functionally equivalent to the standard
|
||||
drop-in algorithms used in parallel mode, but they are available in
|
||||
a separate namespace as GNU extensions and may be used in programs
|
||||
compiled with either release mode or with parallel mode. The
|
||||
following table provides the names and headers of the parallel
|
||||
algorithms:
|
||||
</p>
|
||||
|
||||
|
||||
<table title="Parallel algorithms" border="1">
|
||||
<tr>
|
||||
<th>Algorithm</th>
|
||||
<th>Header</th>
|
||||
<th>Parallel algorithm</th>
|
||||
<th>Parallel header</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>std::accumulate</td>
|
||||
<td><numeric></td>
|
||||
<td>__gnu_parallel::accumulate</td>
|
||||
<td><parallel/numeric></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>std::adjacent_difference</td>
|
||||
<td><numeric></td>
|
||||
<td>__gnu_parallel::adjacent_difference</td>
|
||||
<td><parallel/numeric></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>std::inner_product</td>
|
||||
<td><numeric></td>
|
||||
<td>__gnu_parallel::inner_product</td>
|
||||
<td><parallel/numeric></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>std::partial_sum</td>
|
||||
<td><numeric></td>
|
||||
<td>__gnu_parallel::partial_sum</td>
|
||||
<td><parallel/numeric></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>std::adjacent_find</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::adjacent_find</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::count</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::count</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::count_if</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::count_if</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::equal</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::equal</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::find</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::find</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::find_if</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::find_if</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::find_first_of</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::find_first_of</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::for_each</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::for_each</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::generate</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::generate</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::generate_n</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::generate_n</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::lexicographical_compare</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::lexicographical_compare</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::mismatch</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::mismatch</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::search</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::search</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::search_n</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::search_n</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::transform</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::transform</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::replace</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::replace</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::replace_if</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::replace_if</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::max_element</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::max_element</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::merge</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::merge</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::min_element</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::min_element</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::nth_element</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::nth_element</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::partial_sort</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::partial_sort</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::partition</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::partition</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::random_shuffle</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::random_shuffle</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::set_union</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::set_union</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::set_intersection</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::set_intersection</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::set_symmetric_difference</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::set_symmetric_difference</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::set_difference</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::set_difference</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::sort</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::sort</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::stable_sort</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::stable_sort</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::unique_copy</td>
|
||||
<td><algorithm></td>
|
||||
<td>__gnu_parallel::unique_copy</td>
|
||||
<td><parallel/algorithm></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<h4 class="left">Parallel mode semantics</h4>
|
||||
<p> Something about exception safety, interaction with threads,
|
||||
etc. Goal is to have the usual constraints of the STL with respect to
|
||||
exception safety and threads, but add in support for parallel
|
||||
computing.</p>
|
||||
|
||||
<p> Something about compile-time settings and configuration, ie using
|
||||
<code>__gnu_parallel::Settings</code>. XXX Up in the air.</p>
|
||||
|
||||
<h4 class="left">Interface basics and relevant namespaces</h4>
|
||||
|
||||
<p> Two namespaces contain the parallel mode:
|
||||
<code>std::__parallel</code> and <code>__gnu_parallel</code>.
|
||||
</p>
|
||||
|
||||
<p> One namespace contain versions of code that are explicitly sequential:
|
||||
<code>__gnu_serial</code>.
|
||||
</p>
|
||||
|
||||
<p> Parallel implementations of the sequential standard components are
|
||||
defined in <code>namespace std::__parallel</code>. For instance,
|
||||
<code>std::transform</code> from <algorithm> has a parallel
|
||||
counterpart in <code>std::__parallel::transform</code> from
|
||||
<parallel/algorithm>. In addition, these parallel
|
||||
implementatations are injected into <code>namespace
|
||||
__gnu_parallel</code> with using declarations.
|
||||
</p>
|
||||
|
||||
<p> Support and infrastructure is in <code>namespace __gnu_parallel</code>.
|
||||
</p>
|
||||
|
||||
<p> More information, and an organized index of types and functions
|
||||
related to the parallel mode on a per-namespace basis, can be found in
|
||||
the generated source documentation.
|
||||
</p>
|
||||
|
||||
<h4 class="left">Testing</h4>
|
||||
|
||||
<p> Both the normal conformance and regression tests and the
|
||||
supplemental performance tests work.</p>
|
||||
|
||||
<p> To run the conformance and regression tests with the parallel mode
|
||||
active,</p>
|
||||
<code>make check-parallel</code>
|
||||
|
||||
<p>The log and summary files for conformance testing are in the
|
||||
<code>testsuite/parallel</code> directory.</p>
|
||||
|
||||
<p> To run the performance tests with the parallel mode active, </p>
|
||||
<code>make check-performance-parallel</code>
|
||||
|
||||
<p>The result file for performance testing are in the
|
||||
<code>testsuite</code> directory, in the file
|
||||
<code>libstdc++_performance.sum</code>. In addition, the policy-based
|
||||
containers have their own visualizations, which have additional
|
||||
software dependencies than the usual bare-boned text file, and can be
|
||||
generated by using the <code>make doc-performance</code> rule in the
|
||||
testsuite's Makefile.</p>
|
||||
|
||||
<p>Return <a href="#top">to the top of the page</a> or
|
||||
<a href="http://gcc.gnu.org/libstdc++/">to the libstdc++ homepage</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<!-- ####################################################### -->
|
||||
|
||||
<hr />
|
||||
<p class="fineprint"><em>
|
||||
See <a href="17_intro/license.html">license.html</a> for copying conditions.
|
||||
Comments and suggestions are welcome, and may be sent to
|
||||
<a href="mailto:libstdc++@gcc.gnu.org">the libstdc++ mailing list</a>.
|
||||
</em></p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -70,6 +70,7 @@ std_headers = \
|
||||
bits_srcdir = ${glibcxx_srcdir}/include/bits
|
||||
bits_builddir = ./bits
|
||||
bits_headers = \
|
||||
${bits_srcdir}/algorithmfwd.h \
|
||||
${bits_srcdir}/allocator.h \
|
||||
${bits_srcdir}/basic_ios.h \
|
||||
${bits_srcdir}/basic_ios.tcc \
|
||||
@ -730,6 +731,58 @@ debug_headers = \
|
||||
${debug_srcdir}/string \
|
||||
${debug_srcdir}/vector
|
||||
|
||||
# Parallel mode headers
|
||||
parallel_srcdir = ${glibcxx_srcdir}/include/parallel
|
||||
parallel_builddir = ./parallel
|
||||
parallel_headers = \
|
||||
${parallel_srcdir}/algorithm \
|
||||
${parallel_srcdir}/algobase.h \
|
||||
${parallel_srcdir}/algo.h \
|
||||
${parallel_srcdir}/algorithm \
|
||||
${parallel_srcdir}/algorithmfwd.h \
|
||||
${parallel_srcdir}/balanced_quicksort.h \
|
||||
${parallel_srcdir}/base.h \
|
||||
${parallel_srcdir}/basic_iterator.h \
|
||||
${parallel_srcdir}/checkers.h \
|
||||
${parallel_srcdir}/compatibility.h \
|
||||
${parallel_srcdir}/compiletime_settings.h \
|
||||
${parallel_srcdir}/equally_split.h \
|
||||
${parallel_srcdir}/features.h \
|
||||
${parallel_srcdir}/find.h \
|
||||
${parallel_srcdir}/find_selectors.h \
|
||||
${parallel_srcdir}/for_each.h \
|
||||
${parallel_srcdir}/for_each_selectors.h \
|
||||
${parallel_srcdir}/iterator.h \
|
||||
${parallel_srcdir}/list_partition.h \
|
||||
${parallel_srcdir}/losertree.h \
|
||||
${parallel_srcdir}/merge.h \
|
||||
${parallel_srcdir}/multiseq_selection.h \
|
||||
${parallel_srcdir}/multiway_merge.h \
|
||||
${parallel_srcdir}/multiway_mergesort.h \
|
||||
${parallel_srcdir}/numeric \
|
||||
${parallel_srcdir}/numericfwd.h \
|
||||
${parallel_srcdir}/omp_loop.h \
|
||||
${parallel_srcdir}/omp_loop_static.h \
|
||||
${parallel_srcdir}/parallel.h \
|
||||
${parallel_srcdir}/par_loop.h \
|
||||
${parallel_srcdir}/partial_sum.h \
|
||||
${parallel_srcdir}/partition.h \
|
||||
${parallel_srcdir}/queue.h \
|
||||
${parallel_srcdir}/quicksort.h \
|
||||
${parallel_srcdir}/random_number.h \
|
||||
${parallel_srcdir}/random_shuffle.h \
|
||||
${parallel_srcdir}/search.h \
|
||||
${parallel_srcdir}/set_operations.h \
|
||||
${parallel_srcdir}/settings.h \
|
||||
${parallel_srcdir}/sort.h \
|
||||
${parallel_srcdir}/tags.h \
|
||||
${parallel_srcdir}/timing.h \
|
||||
${parallel_srcdir}/tree.h \
|
||||
${parallel_srcdir}/types.h \
|
||||
${parallel_srcdir}/unique_copy.h \
|
||||
${parallel_srcdir}/workstealing.h
|
||||
|
||||
|
||||
# Some of the different "C" header models need extra files.
|
||||
# Some "C" header schemes require the "C" compatibility headers.
|
||||
# For --enable-cheaders=c_std
|
||||
@ -791,7 +844,8 @@ pch1_output_anchor = ${host_builddir}/stdc++.h
|
||||
pch1_output_installdir = ${host_installdir}/stdc++.h.gch
|
||||
pch1a_output = ${pch1_output_builddir}/O0g.gch
|
||||
pch1b_output = ${pch1_output_builddir}/O2g.gch
|
||||
pch1_output = ${pch1a_output} ${pch1b_output}
|
||||
pch1c_output = ${pch1_output_builddir}/O2gp.gch
|
||||
pch1_output = ${pch1a_output} ${pch1b_output} ${pch1c_output}
|
||||
|
||||
pch2_source = ${glibcxx_srcdir}/include/precompiled/stdtr1c++.h
|
||||
pch2_output_builddir = ${host_builddir}/stdtr1c++.h.gch
|
||||
@ -823,7 +877,7 @@ 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-host
|
||||
stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host
|
||||
|
||||
# List of all files that are created by explicit building, editing, or
|
||||
# catenation.
|
||||
@ -980,6 +1034,15 @@ stamp-debug: ${debug_headers}
|
||||
fi ;\
|
||||
$(STAMP) stamp-debug
|
||||
|
||||
stamp-parallel: ${parallel_headers}
|
||||
@if [ ! -d "${parallel_builddir}" ]; then \
|
||||
mkdir -p ${parallel_builddir} ;\
|
||||
fi ;\
|
||||
if [ ! -f stamp-parallel ]; then \
|
||||
(cd ${parallel_builddir} && @LN_S@ $? . || true) ;\
|
||||
fi ;\
|
||||
$(STAMP) stamp-parallel
|
||||
|
||||
stamp-${host_alias}:
|
||||
@if [ ! -d ${host_builddir} ]; then \
|
||||
mkdir -p ${host_builddir} ;\
|
||||
@ -1091,7 +1154,7 @@ ${host_builddir}/gthr-default.h: ${toplevel_srcdir}/gcc/${glibcxx_thread_h} \
|
||||
-e 's,^#include "\(.*\)",#include <bits/\1>,g' \
|
||||
< ${toplevel_srcdir}/gcc/${glibcxx_thread_h} > $@
|
||||
|
||||
# Build two precompiled C++ includes, stdc++.h.gch/*.gch
|
||||
# Build three precompiled C++ includes, stdc++.h.gch/*.gch
|
||||
${pch1a_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
|
||||
if [ ! -d "${pch1_output_builddir}" ]; then \
|
||||
mkdir -p ${pch1_output_builddir}; \
|
||||
@ -1106,6 +1169,14 @@ ${pch1b_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
|
||||
$(CXX) $(PCHFLAGS) $(AM_CPPFLAGS) -O2 -g ${pch1_source} -o $@
|
||||
touch ${pch1_output_anchor}
|
||||
|
||||
${pch1c_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
|
||||
if [ ! -d "${pch1_output_builddir}" ]; then \
|
||||
mkdir -p ${pch1_output_builddir}; \
|
||||
fi; \
|
||||
CXX_PARALLEL_FLAGS="-fgomp -march=native";
|
||||
$(CXX) $(PCHFLAGS) $(AM_CPPFLAGS) -O2 -g $(CXX_PARALLEL_FLAGS) ${pch1_source} -o $@
|
||||
touch ${pch1_output_anchor}
|
||||
|
||||
# Build a precompiled TR1 include, stdtr1c++.h.gch/O2.gch
|
||||
${pch2_output}: ${pch2_source} ${pch1_output}
|
||||
if [ ! -d "${pch2_output_builddir}" ]; then \
|
||||
@ -1217,6 +1288,9 @@ install-headers:
|
||||
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${debug_builddir}
|
||||
for file in ${debug_headers}; do \
|
||||
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${debug_builddir}; done
|
||||
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${parallel_builddir}
|
||||
for file in ${parallel_headers}; do \
|
||||
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${parallel_builddir}; done
|
||||
$(mkinstalldirs) $(DESTDIR)${host_installdir}
|
||||
for file in ${host_headers} ${host_headers_extra} \
|
||||
${thread_host_headers}; do \
|
||||
|
@ -71,6 +71,7 @@ AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@
|
||||
ATOMIC_FLAGS = @ATOMIC_FLAGS@
|
||||
ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
@ -108,6 +109,8 @@ ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_PARALLEL_FALSE = @ENABLE_PARALLEL_FALSE@
|
||||
ENABLE_PARALLEL_TRUE = @ENABLE_PARALLEL_TRUE@
|
||||
ENABLE_SYMVERS_DARWIN_FALSE = @ENABLE_SYMVERS_DARWIN_FALSE@
|
||||
ENABLE_SYMVERS_DARWIN_TRUE = @ENABLE_SYMVERS_DARWIN_TRUE@
|
||||
ENABLE_SYMVERS_FALSE = @ENABLE_SYMVERS_FALSE@
|
||||
@ -316,6 +319,7 @@ std_headers = \
|
||||
bits_srcdir = ${glibcxx_srcdir}/include/bits
|
||||
bits_builddir = ./bits
|
||||
bits_headers = \
|
||||
${bits_srcdir}/algorithmfwd.h \
|
||||
${bits_srcdir}/allocator.h \
|
||||
${bits_srcdir}/basic_ios.h \
|
||||
${bits_srcdir}/basic_ios.tcc \
|
||||
@ -965,6 +969,58 @@ debug_headers = \
|
||||
${debug_srcdir}/string \
|
||||
${debug_srcdir}/vector
|
||||
|
||||
|
||||
# Parallel mode headers
|
||||
parallel_srcdir = ${glibcxx_srcdir}/include/parallel
|
||||
parallel_builddir = ./parallel
|
||||
parallel_headers = \
|
||||
${parallel_srcdir}/algorithm \
|
||||
${parallel_srcdir}/algobase.h \
|
||||
${parallel_srcdir}/algo.h \
|
||||
${parallel_srcdir}/algorithm \
|
||||
${parallel_srcdir}/algorithmfwd.h \
|
||||
${parallel_srcdir}/balanced_quicksort.h \
|
||||
${parallel_srcdir}/base.h \
|
||||
${parallel_srcdir}/basic_iterator.h \
|
||||
${parallel_srcdir}/checkers.h \
|
||||
${parallel_srcdir}/compatibility.h \
|
||||
${parallel_srcdir}/compiletime_settings.h \
|
||||
${parallel_srcdir}/equally_split.h \
|
||||
${parallel_srcdir}/features.h \
|
||||
${parallel_srcdir}/find.h \
|
||||
${parallel_srcdir}/find_selectors.h \
|
||||
${parallel_srcdir}/for_each.h \
|
||||
${parallel_srcdir}/for_each_selectors.h \
|
||||
${parallel_srcdir}/iterator.h \
|
||||
${parallel_srcdir}/list_partition.h \
|
||||
${parallel_srcdir}/losertree.h \
|
||||
${parallel_srcdir}/merge.h \
|
||||
${parallel_srcdir}/multiseq_selection.h \
|
||||
${parallel_srcdir}/multiway_merge.h \
|
||||
${parallel_srcdir}/multiway_mergesort.h \
|
||||
${parallel_srcdir}/numeric \
|
||||
${parallel_srcdir}/numericfwd.h \
|
||||
${parallel_srcdir}/omp_loop.h \
|
||||
${parallel_srcdir}/omp_loop_static.h \
|
||||
${parallel_srcdir}/parallel.h \
|
||||
${parallel_srcdir}/par_loop.h \
|
||||
${parallel_srcdir}/partial_sum.h \
|
||||
${parallel_srcdir}/partition.h \
|
||||
${parallel_srcdir}/queue.h \
|
||||
${parallel_srcdir}/quicksort.h \
|
||||
${parallel_srcdir}/random_number.h \
|
||||
${parallel_srcdir}/random_shuffle.h \
|
||||
${parallel_srcdir}/search.h \
|
||||
${parallel_srcdir}/set_operations.h \
|
||||
${parallel_srcdir}/settings.h \
|
||||
${parallel_srcdir}/sort.h \
|
||||
${parallel_srcdir}/tags.h \
|
||||
${parallel_srcdir}/timing.h \
|
||||
${parallel_srcdir}/tree.h \
|
||||
${parallel_srcdir}/types.h \
|
||||
${parallel_srcdir}/unique_copy.h \
|
||||
${parallel_srcdir}/workstealing.h
|
||||
|
||||
@GLIBCXX_C_HEADERS_EXTRA_FALSE@c_base_headers_extra =
|
||||
|
||||
# Some of the different "C" header models need extra files.
|
||||
@ -1020,7 +1076,8 @@ pch1_output_anchor = ${host_builddir}/stdc++.h
|
||||
pch1_output_installdir = ${host_installdir}/stdc++.h.gch
|
||||
pch1a_output = ${pch1_output_builddir}/O0g.gch
|
||||
pch1b_output = ${pch1_output_builddir}/O2g.gch
|
||||
pch1_output = ${pch1a_output} ${pch1b_output}
|
||||
pch1c_output = ${pch1_output_builddir}/O2gp.gch
|
||||
pch1_output = ${pch1a_output} ${pch1b_output} ${pch1c_output}
|
||||
pch2_source = ${glibcxx_srcdir}/include/precompiled/stdtr1c++.h
|
||||
pch2_output_builddir = ${host_builddir}/stdtr1c++.h.gch
|
||||
pch2_output_anchor = ${host_builddir}/stdtr1c++.h
|
||||
@ -1047,7 +1104,7 @@ PCHFLAGS = -Winvalid-pch -Wno-deprecated -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-host
|
||||
stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host
|
||||
|
||||
|
||||
# List of all files that are created by explicit building, editing, or
|
||||
@ -1374,6 +1431,15 @@ stamp-debug: ${debug_headers}
|
||||
fi ;\
|
||||
$(STAMP) stamp-debug
|
||||
|
||||
stamp-parallel: ${parallel_headers}
|
||||
@if [ ! -d "${parallel_builddir}" ]; then \
|
||||
mkdir -p ${parallel_builddir} ;\
|
||||
fi ;\
|
||||
if [ ! -f stamp-parallel ]; then \
|
||||
(cd ${parallel_builddir} && @LN_S@ $? . || true) ;\
|
||||
fi ;\
|
||||
$(STAMP) stamp-parallel
|
||||
|
||||
stamp-${host_alias}:
|
||||
@if [ ! -d ${host_builddir} ]; then \
|
||||
mkdir -p ${host_builddir} ;\
|
||||
@ -1476,7 +1542,7 @@ ${host_builddir}/gthr-default.h: ${toplevel_srcdir}/gcc/${glibcxx_thread_h} \
|
||||
-e 's,^#include "\(.*\)",#include <bits/\1>,g' \
|
||||
< ${toplevel_srcdir}/gcc/${glibcxx_thread_h} > $@
|
||||
|
||||
# Build two precompiled C++ includes, stdc++.h.gch/*.gch
|
||||
# Build three precompiled C++ includes, stdc++.h.gch/*.gch
|
||||
${pch1a_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
|
||||
if [ ! -d "${pch1_output_builddir}" ]; then \
|
||||
mkdir -p ${pch1_output_builddir}; \
|
||||
@ -1491,6 +1557,14 @@ ${pch1b_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
|
||||
$(CXX) $(PCHFLAGS) $(AM_CPPFLAGS) -O2 -g ${pch1_source} -o $@
|
||||
touch ${pch1_output_anchor}
|
||||
|
||||
${pch1c_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
|
||||
if [ ! -d "${pch1_output_builddir}" ]; then \
|
||||
mkdir -p ${pch1_output_builddir}; \
|
||||
fi; \
|
||||
CXX_PARALLEL_FLAGS="-fgomp -march=native";
|
||||
$(CXX) $(PCHFLAGS) $(AM_CPPFLAGS) -O2 -g $(CXX_PARALLEL_FLAGS) ${pch1_source} -o $@
|
||||
touch ${pch1_output_anchor}
|
||||
|
||||
# Build a precompiled TR1 include, stdtr1c++.h.gch/O2.gch
|
||||
${pch2_output}: ${pch2_source} ${pch1_output}
|
||||
if [ ! -d "${pch2_output_builddir}" ]; then \
|
||||
@ -1599,6 +1673,9 @@ install-headers:
|
||||
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${debug_builddir}
|
||||
for file in ${debug_headers}; do \
|
||||
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${debug_builddir}; done
|
||||
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${parallel_builddir}
|
||||
for file in ${parallel_headers}; do \
|
||||
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${parallel_builddir}; done
|
||||
$(mkinstalldirs) $(DESTDIR)${host_installdir}
|
||||
for file in ${host_headers} ${host_headers_extra} \
|
||||
${thread_host_headers}; do \
|
||||
|
597
libstdc++-v3/include/bits/algorithmfwd.h
Normal file
597
libstdc++-v3/include/bits/algorithmfwd.h
Normal file
@ -0,0 +1,597 @@
|
||||
// <algorithm> declarations -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING. If not, write to the Free
|
||||
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
// USA.
|
||||
|
||||
/** @file bits/algorithmfwd.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* You should not attempt to use it directly.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
adjacent_find
|
||||
binary_search
|
||||
copy
|
||||
copy_backward
|
||||
count
|
||||
count_if
|
||||
equal
|
||||
equal_range
|
||||
fill
|
||||
fill_n
|
||||
find
|
||||
find_end
|
||||
find_first_of
|
||||
find_if
|
||||
for_each
|
||||
generate
|
||||
generate_n
|
||||
includes
|
||||
inplace_merge
|
||||
iter_swap
|
||||
lexicographical_compare
|
||||
lower_bound
|
||||
make_heap
|
||||
max
|
||||
max_element
|
||||
merge
|
||||
min
|
||||
min_element
|
||||
mismatch
|
||||
next_permutation
|
||||
nth_element
|
||||
parital_sort
|
||||
partial_sort_copy
|
||||
partition
|
||||
pop_heap
|
||||
prev_permutation
|
||||
push_heap
|
||||
random_shuffle
|
||||
remove
|
||||
remove_copy
|
||||
remove_copy_if
|
||||
remove_if
|
||||
replace
|
||||
replace_copy
|
||||
replace_copy_if
|
||||
replace_if
|
||||
reverse
|
||||
reverse_copy
|
||||
rotate
|
||||
rotate_copy
|
||||
search
|
||||
search_n
|
||||
set_differernce
|
||||
set_intersection
|
||||
set_symmetric_difference
|
||||
set_union
|
||||
sort
|
||||
sort_heap
|
||||
stable_partition
|
||||
stable_sort
|
||||
stable_sort
|
||||
swap
|
||||
swap_ranges
|
||||
transform
|
||||
unique
|
||||
unique_copy
|
||||
upper_bound
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ALGORITHMFWD_H
|
||||
#define _GLIBCXX_ALGORITHMFWD_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <bits/stl_pair.h>
|
||||
#include <bits/stl_iterator_base_types.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
|
||||
// adjacent_find
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
bool
|
||||
binary_search(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
bool
|
||||
binary_search(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
_OIter
|
||||
copy(_IIter, _IIter, _OIter);
|
||||
|
||||
template<typename _BIter1, typename _BIter2>
|
||||
_BIter2
|
||||
copy_backward (_BIter1, _BIter1, _BIter2);
|
||||
|
||||
// count
|
||||
// count_if
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
pair<_FIter, _FIter>
|
||||
equal_range(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
pair<_FIter, _FIter>
|
||||
equal_range(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
void
|
||||
fill(_FIter, _FIter, const _Tp&);
|
||||
|
||||
/*
|
||||
XXX NB: return type different from ISO C++.
|
||||
template<typename _OIter, typename _Size, typename _Tp>
|
||||
void
|
||||
fill_n(_OIter, _Size, const _Tp&);
|
||||
*/
|
||||
|
||||
template<typename _OIter, typename _Size, typename _Tp>
|
||||
_OIter
|
||||
fill_n(_OIter, _Size, const _Tp&);
|
||||
|
||||
// find
|
||||
// find_end
|
||||
// find_first_of
|
||||
// find_if
|
||||
// for_each
|
||||
// generate
|
||||
// generate_n
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
bool
|
||||
includes(_IIter1, _IIter1, _IIter2, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _Compare>
|
||||
bool
|
||||
includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare);
|
||||
|
||||
template<typename _BIter>
|
||||
void
|
||||
inplace_merge(_BIter, _BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
void
|
||||
inplace_merge(_BIter, _BIter, _BIter, _Compare);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
void
|
||||
iter_swap(_FIter1, _FIter2);
|
||||
|
||||
// Specializations for char and unsigned char.
|
||||
inline bool
|
||||
lexicographical_compare(const unsigned char*, const unsigned char*,
|
||||
const unsigned char*, const unsigned char*);
|
||||
|
||||
inline bool
|
||||
lexicographical_compare(const char*, const char*, const char*, const char*);
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_FIter
|
||||
lower_bound(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_FIter
|
||||
lower_bound(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
make_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
make_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
const _Tp&
|
||||
max(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
const _Tp&
|
||||
max(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
// max_element
|
||||
// merge
|
||||
|
||||
template<typename _Tp>
|
||||
const _Tp&
|
||||
min(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
const _Tp&
|
||||
min(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
// min_element
|
||||
// mismatch
|
||||
|
||||
template<typename _BIter>
|
||||
bool
|
||||
next_permutation(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
bool
|
||||
next_permutation(_BIter, _BIter, _Compare);
|
||||
|
||||
// nth_element
|
||||
// partial_sort
|
||||
|
||||
template<typename _IIter, typename _RAIter>
|
||||
_RAIter
|
||||
partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _IIter, typename _RAIter, typename _Compare>
|
||||
_RAIter
|
||||
partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
pop_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
pop_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter>
|
||||
bool
|
||||
prev_permutation(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
bool
|
||||
prev_permutation(_BIter, _BIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
push_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
push_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
// random_shuffle
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_FIter
|
||||
remove(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Predicate>
|
||||
_FIter
|
||||
remove_if(_FIter, _FIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Tp>
|
||||
_OIter
|
||||
remove_copy(_IIter, _IIter, _OIter, const _Tp&);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Predicate>
|
||||
_OIter
|
||||
remove_copy_if(_IIter, _IIter, _OIter, _Predicate);
|
||||
|
||||
// replace
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Tp>
|
||||
_OIter
|
||||
replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Iter, typename _OIter, typename _Predicate, typename _Tp>
|
||||
_OIter
|
||||
replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&);
|
||||
|
||||
// replace_if
|
||||
|
||||
template<typename _BIter>
|
||||
void
|
||||
reverse(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _OIter>
|
||||
_OIter
|
||||
reverse_copy(_BIter, _BIter, _OIter);
|
||||
|
||||
template<typename _FIter>
|
||||
void
|
||||
rotate(_FIter, _FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _OIter>
|
||||
_OIter
|
||||
rotate_copy (_FIter, _FIter, _FIter, _OIter);
|
||||
|
||||
// search
|
||||
// search_n
|
||||
// set_difference
|
||||
// set_intersection
|
||||
// set_symmetric_difference
|
||||
// set_union
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
sort_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
sort_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter, typename _Predicate>
|
||||
_BIter
|
||||
stable_partition(_BIter, _BIter, _Predicate);
|
||||
|
||||
template<typename _Tp>
|
||||
void
|
||||
swap(_Tp&, _Tp& b);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter2
|
||||
swap_ranges(_FIter1 first1, _FIter1, _FIter2);
|
||||
|
||||
// transform
|
||||
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
unique(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _BinaryPredicate>
|
||||
_FIter
|
||||
unique(_FIter, _FIter, _BinaryPredicate);
|
||||
|
||||
// unique_copy
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_FIter
|
||||
upper_bound(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_FIter
|
||||
upper_bound(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
_GLIBCXX_END_NAMESPACE
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_P)
|
||||
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
adjacent_find(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _BinaryPredicate>
|
||||
_FIter
|
||||
adjacent_find(_FIter, _FIter, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Tp>
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count(_IIter, _IIter, const _Tp&);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count_if(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
bool
|
||||
equal(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
|
||||
bool
|
||||
equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Tp>
|
||||
_IIter
|
||||
find(_IIter, _IIter, const _Tp&);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter1
|
||||
find_end(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_FIter1
|
||||
find_end(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter1
|
||||
find_first_of(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_FIter1
|
||||
find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_IIter
|
||||
find_if(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _Funct>
|
||||
_Funct
|
||||
for_each(_IIter, _IIter, _Funct);
|
||||
|
||||
template<typename _FIter, typename _Generator>
|
||||
void
|
||||
generate(_FIter, _FIter, _Generator);
|
||||
|
||||
template<typename _OIter, typename _Size, typename _Generator>
|
||||
void
|
||||
generate_n(_OIter, _Size, _Generator);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _Compare>
|
||||
bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
max_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_FIter
|
||||
max_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
min_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_FIter
|
||||
min_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
|
||||
pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter, typename _Predicate>
|
||||
_BIter
|
||||
partition(_BIter, _BIter, _Predicate);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
random_shuffle(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Generator>
|
||||
void
|
||||
random_shuffle(_RAIter, _RAIter, _Generator&);
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
void
|
||||
replace(_FIter, _FIter, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Predicate, typename _Tp>
|
||||
void
|
||||
replace_if(_FIter, _FIter, _Predicate, const _Tp&);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _FIter, typename _Size, typename _Tp>
|
||||
_FIter
|
||||
search_n(_FIter, _FIter, _Size, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Size, typename _Tp,
|
||||
typename _BinaryPredicate>
|
||||
_FIter
|
||||
search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2,
|
||||
_OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _UnaryOperation>
|
||||
_OIter
|
||||
transform(_IIter, _IIter, _OIter, _UnaryOperation);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _BinaryOperation>
|
||||
_OIter
|
||||
transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
_OIter
|
||||
unique_copy(_IIter, _IIter, _OIter);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryPredicate>
|
||||
_OIter
|
||||
unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate);
|
||||
|
||||
_GLIBCXX_END_NESTED_NAMESPACE
|
||||
|
||||
#ifdef _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL
|
||||
# include <parallel/algorithmfwd.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -45,16 +45,7 @@
|
||||
// The current version of the C++ library in compressed ISO date format.
|
||||
#define __GLIBCXX__
|
||||
|
||||
// Macro used to indicate that the native "C" includes, when compiled
|
||||
// as "C++", have declarations in namespace std and not the global
|
||||
// namespace. Note, this is unrelated to possible "C" compatibility
|
||||
// includes that inject C90/C99 names into the global namespace.
|
||||
// XXX May not be necessary
|
||||
#if __cplusplus == 199711L
|
||||
# define _GLIBCXX_NAMESPACE_GLOBAL_INJECTION 1
|
||||
#endif
|
||||
|
||||
// Macros for visibility.
|
||||
// Macros for visibility support.
|
||||
#define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY
|
||||
|
||||
#if _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY
|
||||
@ -63,36 +54,178 @@
|
||||
# define _GLIBCXX_VISIBILITY(V)
|
||||
#endif
|
||||
|
||||
// Macros for controlling various namespace association schemes and modes.
|
||||
// Guide to libstdc++ namespaces.
|
||||
/*
|
||||
namespace std
|
||||
{
|
||||
namespace __debug { }
|
||||
namespace __parallel { }
|
||||
namespace __norm { } // __normative, __shadow, __replaced
|
||||
namespace __cxx1998 { }
|
||||
|
||||
namespace tr1 { }
|
||||
}
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
namespace __debug { }
|
||||
namespace __norm { }
|
||||
}
|
||||
*/
|
||||
|
||||
// Macros for activating various namespace association modes.
|
||||
// _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
|
||||
// _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
|
||||
// _GLIBCXX_NAMESPACE_ASSOCIATION_CXX200x
|
||||
// _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL
|
||||
// _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
|
||||
|
||||
#ifdef _GLIBCXX_DEBUG
|
||||
# define _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG 1
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# define _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL 1
|
||||
#endif
|
||||
|
||||
#define _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
|
||||
|
||||
// Macros for namespace scope.
|
||||
// Defined if any namespace association modes are active.
|
||||
#if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG \
|
||||
|| _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL \
|
||||
|| _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
|
||||
# define _GLIBCXX_USE_NAMESPACE_ASSOCIATION 1
|
||||
#endif
|
||||
|
||||
// Macros for namespace scope. Either namespace std:: or __gnu_cxx::,
|
||||
// or the name of some nested namespace within it.
|
||||
// _GLIBCXX_STD
|
||||
// _GLIBCXX_STD_D
|
||||
// _GLIBCXX_STD_P
|
||||
// _GLIBCXX_EXT
|
||||
// _GLIBCXX_EXT_D
|
||||
// _GLIBCXX_EXT_P
|
||||
|
||||
//
|
||||
// Macros for enclosing namepaces and possibly nested namespaces.
|
||||
// _GLIBCXX_BEGIN_NAMESPACE
|
||||
// _GLIBCXX_END_NAMESPACE
|
||||
// _GLIBCXX_BEGIN_NESTED_NAMESPACE
|
||||
// _GLIBCXX_END_NESTED_NAMESPACE
|
||||
#if _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
|
||||
// _GLIBCXX_BEGIN_POTENTIAL_NESTED_NAMESPACE
|
||||
// _GLIBCXX_END_POTENTIAL_NESTED_NAMESPACE
|
||||
#ifndef _GLIBCXX_USE_NAMESPACE_ASSOCIATION
|
||||
# define _GLIBCXX_STD_D _GLIBCXX_STD
|
||||
# define _GLIBCXX_STD_P _GLIBCXX_STD
|
||||
# define _GLIBCXX_STD std
|
||||
# define _GLIBCXX_EXT_D _GLIBCXX_EXT
|
||||
# define _GLIBCXX_EXT_P _GLIBCXX_EXT
|
||||
# define _GLIBCXX_EXT __gnu_cxx
|
||||
# define _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, Y) _GLIBCXX_BEGIN_NAMESPACE(X)
|
||||
# define _GLIBCXX_END_NESTED_NAMESPACE _GLIBCXX_END_NAMESPACE
|
||||
# define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY(default) {
|
||||
# define _GLIBCXX_END_NAMESPACE }
|
||||
#else
|
||||
|
||||
# if _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION // && not anything else
|
||||
# define _GLIBCXX_STD_D _GLIBCXX_STD
|
||||
# define _GLIBCXX_STD_P _GLIBCXX_STD
|
||||
# define _GLIBCXX_STD _6
|
||||
# define _GLIBCXX_EXT _6
|
||||
# define _GLIBCXX_BEGIN_NAMESPACE(X) _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, _6)
|
||||
# define _GLIBCXX_END_NAMESPACE _GLIBCXX_END_NESTED_NAMESPACE
|
||||
# endif
|
||||
|
||||
// debug
|
||||
# if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG && !_GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL
|
||||
# define _GLIBCXX_STD_D __norm
|
||||
# define _GLIBCXX_STD_P _GLIBCXX_STD
|
||||
# define _GLIBCXX_STD __cxx1998
|
||||
# define _GLIBCXX_EXT_D __norm
|
||||
# define _GLIBCXX_EXT_P _GLIBCXX_EXT
|
||||
# define _GLIBCXX_EXT __cxx1998
|
||||
# define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY(default) {
|
||||
# define _GLIBCXX_END_NAMESPACE }
|
||||
# define _GLIBCXX_EXTERN_TEMPLATE 0
|
||||
# endif
|
||||
|
||||
// parallel
|
||||
# if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL && !_GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
|
||||
# define _GLIBCXX_STD_D _GLIBCXX_STD
|
||||
# define _GLIBCXX_STD_P __norm
|
||||
# define _GLIBCXX_STD __cxx1998
|
||||
# define _GLIBCXX_EXT_D _GLIBCXX_EXT
|
||||
# define _GLIBCXX_EXT_P __norm
|
||||
# define _GLIBCXX_EXT __cxx1998
|
||||
# define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY(default) {
|
||||
# define _GLIBCXX_END_NAMESPACE }
|
||||
# define _GLIBCXX_EXTERN_TEMPLATE 0
|
||||
# endif
|
||||
|
||||
// debug + parallel
|
||||
# if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL && _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
|
||||
# define _GLIBCXX_STD_D __norm
|
||||
# define _GLIBCXX_STD_P __norm
|
||||
# define _GLIBCXX_STD __cxx1998
|
||||
# define _GLIBCXX_EXT_D __norm
|
||||
# define _GLIBCXX_EXT_P __norm
|
||||
# define _GLIBCXX_EXT __gnu_cxx
|
||||
# define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY(default) {
|
||||
# define _GLIBCXX_END_NAMESPACE }
|
||||
# define _GLIBCXX_EXTERN_TEMPLATE 0
|
||||
# endif
|
||||
|
||||
# if __NO_INLINE__ && !__GXX_WEAK__
|
||||
# warning currently using namepace associated mode which may fail \
|
||||
without inlining due to lack of weak symbols
|
||||
# endif
|
||||
|
||||
# define _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, Y) namespace X { namespace Y _GLIBCXX_VISIBILITY(default) {
|
||||
# define _GLIBCXX_END_NESTED_NAMESPACE } }
|
||||
# define _GLIBCXX_BEGIN_NAMESPACE(X) _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, _6)
|
||||
# define _GLIBCXX_END_NAMESPACE _GLIBCXX_END_NESTED_NAMESPACE
|
||||
#else
|
||||
# define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY(default) {
|
||||
# define _GLIBCXX_END_NAMESPACE }
|
||||
# if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
|
||||
# define _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, Y) namespace X { namespace Y _GLIBCXX_VISIBILITY(default) {
|
||||
# define _GLIBCXX_END_NESTED_NAMESPACE } }
|
||||
# else
|
||||
# define _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, Y) _GLIBCXX_BEGIN_NAMESPACE(X)
|
||||
# define _GLIBCXX_END_NESTED_NAMESPACE _GLIBCXX_END_NAMESPACE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Namespace associations for debug mode.
|
||||
#if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
|
||||
namespace std
|
||||
{
|
||||
namespace __norm { }
|
||||
namespace __debug { }
|
||||
namespace __cxx1998 { }
|
||||
|
||||
using namespace __debug __attribute__ ((strong));
|
||||
using namespace __cxx1998 __attribute__ ((strong));
|
||||
}
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
namespace __norm { }
|
||||
namespace __debug { }
|
||||
namespace __cxx1998 { }
|
||||
|
||||
using namespace __debug __attribute__ ((strong));
|
||||
using namespace __cxx1998 __attribute__ ((strong));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Namespace associations for parallel mode.
|
||||
#if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL
|
||||
namespace std
|
||||
{
|
||||
namespace __norm { }
|
||||
namespace __parallel { }
|
||||
namespace __cxx1998 { }
|
||||
|
||||
using namespace __parallel __attribute__ ((strong));
|
||||
using namespace __cxx1998 __attribute__ ((strong));
|
||||
}
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
namespace __norm { }
|
||||
namespace __parallel { }
|
||||
namespace __cxx1998 { }
|
||||
|
||||
using namespace __parallel __attribute__ ((strong));
|
||||
using namespace __cxx1998 __attribute__ ((strong));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Namespace associations for versioning mode.
|
||||
@ -119,38 +252,6 @@ namespace std
|
||||
}
|
||||
#endif
|
||||
|
||||
// Namespace associations for debug mode.
|
||||
#if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
|
||||
namespace std
|
||||
{
|
||||
namespace __norm { }
|
||||
namespace __debug { }
|
||||
using namespace __debug __attribute__ ((strong));
|
||||
}
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
namespace __norm { }
|
||||
namespace __debug { }
|
||||
using namespace __debug __attribute__ ((strong));
|
||||
}
|
||||
|
||||
# define _GLIBCXX_STD __norm
|
||||
# define _GLIBCXX_EXT __norm
|
||||
# define _GLIBCXX_EXTERN_TEMPLATE 0
|
||||
# if __NO_INLINE__ && !__GXX_WEAK__
|
||||
# warning debug mode without inlining may fail due to lack of weak symbols
|
||||
# endif
|
||||
#else
|
||||
#if _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
|
||||
# define _GLIBCXX_STD _6
|
||||
# define _GLIBCXX_EXT _6
|
||||
#else
|
||||
# define _GLIBCXX_STD std
|
||||
# define _GLIBCXX_EXT __gnu_cxx
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define if compatibility should be provided for -mlong-double-64.
|
||||
#undef _GLIBCXX_LONG_DOUBLE_COMPAT
|
||||
|
||||
@ -193,6 +294,14 @@ _GLIBCXX_END_NAMESPACE
|
||||
# define _GLIBCXX_WEAK_DEFINITION
|
||||
#endif
|
||||
|
||||
// Macro used to indicate that the native "C" includes, when compiled
|
||||
// as "C++", have declarations in namespace std and not the global
|
||||
// namespace. Note, this is unrelated to possible "C" compatibility
|
||||
// includes that inject C90/C99 names into the global namespace.
|
||||
#if __cplusplus == 199711L
|
||||
# define _GLIBCXX_NAMESPACE_GLOBAL_INJECTION 1
|
||||
#endif
|
||||
|
||||
// The remainder of the prewritten config is automatic; all the
|
||||
// user hooks are listed above.
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/stl_algobase.h> // For copy, fill_n
|
||||
#include <bits/algorithmfwd.h> // std::copy, std::fill_n
|
||||
#include <bits/postypes.h> // For streampos
|
||||
#include <cstdio> // For EOF
|
||||
#include <cwchar> // For WEOF, wmemmove, wmemset, etc.
|
||||
@ -194,6 +194,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
|
||||
char_traits<_CharT>::
|
||||
copy(char_type* __s1, const char_type* __s2, std::size_t __n)
|
||||
{
|
||||
// NB: Inline std::copy so no recursive dependencies.
|
||||
std::copy(__s2, __s2 + __n, __s1);
|
||||
return __s1;
|
||||
}
|
||||
@ -203,6 +204,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
|
||||
char_traits<_CharT>::
|
||||
assign(char_type* __s, std::size_t __n, char_type __a)
|
||||
{
|
||||
// NB: Inline std::fill_n so no recursive dependencies.
|
||||
std::fill_n(__s, __n, __a);
|
||||
return __s;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@
|
||||
#ifndef _DEQUE_TCC
|
||||
#define _DEQUE_TCC 1
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
template <typename _Tp, typename _Alloc>
|
||||
deque<_Tp, _Alloc>&
|
||||
|
@ -62,7 +62,7 @@
|
||||
#ifndef _LIST_TCC
|
||||
#define _LIST_TCC 1
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -65,11 +65,10 @@
|
||||
#include <bits/c++config.h>
|
||||
#include <cstddef>
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/stl_pair.h>
|
||||
#include <bits/cpp_type_traits.h>
|
||||
#include <ext/type_traits.h>
|
||||
#include <ext/numeric_traits.h>
|
||||
#include <bits/stl_iterator_base_types.h>
|
||||
#include <bits/algorithmfwd.h>
|
||||
#include <bits/stl_iterator_base_funcs.h>
|
||||
#include <bits/stl_iterator.h>
|
||||
#include <bits/concept_check.h>
|
||||
@ -596,7 +595,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__niter_base<_ForwardIterator>::__b(__last), __value);
|
||||
}
|
||||
|
||||
|
||||
template<bool>
|
||||
struct __fill_n
|
||||
{
|
||||
@ -678,7 +676,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__value));
|
||||
}
|
||||
|
||||
|
||||
template<bool _BoolType>
|
||||
struct __equal
|
||||
{
|
||||
@ -719,6 +716,90 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
return std::__equal<__simple>::equal(__first1, __last1, __first2);
|
||||
}
|
||||
|
||||
|
||||
template<typename, typename>
|
||||
struct __lc_rai
|
||||
{
|
||||
template<typename _II1, typename _II2>
|
||||
static _II1
|
||||
__newlast1(_II1, _II1 __last1, _II2, _II2)
|
||||
{ return __last1; }
|
||||
|
||||
template<typename _II>
|
||||
static bool
|
||||
__cnd2(_II __first, _II __last)
|
||||
{ return __first != __last; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __lc_rai<random_access_iterator_tag, random_access_iterator_tag>
|
||||
{
|
||||
template<typename _RAI1, typename _RAI2>
|
||||
static _RAI1
|
||||
__newlast1(_RAI1 __first1, _RAI1 __last1,
|
||||
_RAI2 __first2, _RAI2 __last2)
|
||||
{
|
||||
const typename iterator_traits<_RAI1>::difference_type
|
||||
__diff1 = __last1 - __first1;
|
||||
const typename iterator_traits<_RAI2>::difference_type
|
||||
__diff2 = __last2 - __first2;
|
||||
return __diff2 < __diff1 ? __first1 + __diff2 : __last1;
|
||||
}
|
||||
|
||||
template<typename _RAI>
|
||||
static bool
|
||||
__cnd2(_RAI, _RAI)
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
// XXX should these be enabled-if'd for signed/unsigned types instead?
|
||||
inline bool
|
||||
lexicographical_compare(const unsigned char* __first1,
|
||||
const unsigned char* __last1,
|
||||
const unsigned char* __first2,
|
||||
const unsigned char* __last2)
|
||||
{
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
__glibcxx_requires_valid_range(__first2, __last2);
|
||||
|
||||
const size_t __len1 = __last1 - __first1;
|
||||
const size_t __len2 = __last2 - __first2;
|
||||
const int __result = __builtin_memcmp(__first1, __first2,
|
||||
std::min(__len1, __len2));
|
||||
return __result != 0 ? __result < 0 : __len1 < __len2;
|
||||
}
|
||||
|
||||
inline bool
|
||||
lexicographical_compare(const char* __first1, const char* __last1,
|
||||
const char* __first2, const char* __last2)
|
||||
{
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
__glibcxx_requires_valid_range(__first2, __last2);
|
||||
|
||||
if (__gnu_cxx::__numeric_traits<char>::__is_signed)
|
||||
{
|
||||
typedef const signed char* value_type;
|
||||
value_type __f1 = reinterpret_cast<value_type>(__first1);
|
||||
value_type __l1 = reinterpret_cast<value_type>(__last1);
|
||||
value_type __f2 = reinterpret_cast<value_type>(__first2);
|
||||
value_type __l2 = reinterpret_cast<value_type>(__last2);
|
||||
return _GLIBCXX_STD_P::lexicographical_compare(__f1, __l1, __f2, __l2);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef const unsigned char* value_type;
|
||||
value_type __f1 = reinterpret_cast<value_type>(__first1);
|
||||
value_type __l1 = reinterpret_cast<value_type>(__last1);
|
||||
value_type __f2 = reinterpret_cast<value_type>(__first2);
|
||||
value_type __l2 = reinterpret_cast<value_type>(__last2);
|
||||
return _GLIBCXX_STD_P::lexicographical_compare(__f1, __l1, __f2, __l2);
|
||||
}
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_P)
|
||||
|
||||
/**
|
||||
* @brief Tests a range for element-wise equality.
|
||||
* @param first1 An input iterator.
|
||||
@ -752,24 +833,23 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
* @param first1 An input iterator.
|
||||
* @param last1 An input iterator.
|
||||
* @param first2 An input iterator.
|
||||
* @param binary_pred A binary predicate @link s20_3_1_base functor@endlink.
|
||||
* @return A boolean true or false.
|
||||
* @param binary_pred A binary predicate @link s20_3_1_base
|
||||
* functor@endlink.
|
||||
* @return A boolean true or false.
|
||||
*
|
||||
* This compares the elements of two ranges using the binary_pred
|
||||
* parameter, and returns true or
|
||||
* false depending on whether all of the corresponding elements of the
|
||||
* ranges are equal.
|
||||
*/
|
||||
template<typename _InputIterator1, typename _InputIterator2,
|
||||
typename _BinaryPredicate>
|
||||
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
|
||||
inline bool
|
||||
equal(_InputIterator1 __first1, _InputIterator1 __last1,
|
||||
_InputIterator2 __first2,
|
||||
_BinaryPredicate __binary_pred)
|
||||
equal(_IIter1 __first1, _IIter1 __last1,
|
||||
_IIter2 __first2, _BinaryPredicate __binary_pred)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_IIter1>)
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_IIter2>)
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
|
||||
for (; __first1 != __last1; ++__first1, ++__first2)
|
||||
@ -778,43 +858,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename, typename>
|
||||
struct __lc_rai
|
||||
{
|
||||
template<typename _II1, typename _II2>
|
||||
static _II1
|
||||
__newlast1(_II1, _II1 __last1, _II2, _II2)
|
||||
{ return __last1; }
|
||||
|
||||
template<typename _II>
|
||||
static bool
|
||||
__cnd2(_II __first, _II __last)
|
||||
{ return __first != __last; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __lc_rai<random_access_iterator_tag,
|
||||
random_access_iterator_tag>
|
||||
{
|
||||
template<typename _RAI1, typename _RAI2>
|
||||
static _RAI1
|
||||
__newlast1(_RAI1 __first1, _RAI1 __last1,
|
||||
_RAI2 __first2, _RAI2 __last2)
|
||||
{
|
||||
const typename iterator_traits<_RAI1>::difference_type
|
||||
__diff1 = __last1 - __first1;
|
||||
const typename iterator_traits<_RAI2>::difference_type
|
||||
__diff2 = __last2 - __first2;
|
||||
return __diff2 < __diff1 ? __first1 + __diff2 : __last1;
|
||||
}
|
||||
|
||||
template<typename _RAI>
|
||||
static bool
|
||||
__cnd2(_RAI, _RAI)
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Performs "dictionary" comparison on ranges.
|
||||
* @param first1 An input iterator.
|
||||
@ -831,7 +874,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
*/
|
||||
template<typename _II1, typename _II2>
|
||||
bool
|
||||
lexicographical_compare(_II1 __first1, _II1 __last1,
|
||||
lexicographical_compare(_II1 __first1, _II1 __last1,
|
||||
_II2 __first2, _II2 __last2)
|
||||
{
|
||||
typedef typename iterator_traits<_II1>::iterator_category _Category1;
|
||||
@ -882,6 +925,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
{
|
||||
typedef typename iterator_traits<_II1>::iterator_category _Category1;
|
||||
typedef typename iterator_traits<_II2>::iterator_category _Category2;
|
||||
typedef __lc_rai<_Category1, _Category2> __rai_type;
|
||||
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_II1>)
|
||||
@ -889,12 +933,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
__glibcxx_requires_valid_range(__first2, __last2);
|
||||
|
||||
__last1 = __lc_rai<_Category1, _Category2>::__newlast1(__first1,
|
||||
__last1,
|
||||
__first2,
|
||||
__last2);
|
||||
for (; __first1 != __last1
|
||||
&& __lc_rai<_Category1, _Category2>::__cnd2(__first2, __last2);
|
||||
__last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2);
|
||||
for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
|
||||
++__first1, ++__first2)
|
||||
{
|
||||
if (__comp(*__first1, *__first2))
|
||||
@ -905,41 +945,82 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
return __first1 == __last1 && __first2 != __last2;
|
||||
}
|
||||
|
||||
inline bool
|
||||
lexicographical_compare(const unsigned char* __first1,
|
||||
const unsigned char* __last1,
|
||||
const unsigned char* __first2,
|
||||
const unsigned char* __last2)
|
||||
{
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
__glibcxx_requires_valid_range(__first2, __last2);
|
||||
|
||||
const size_t __len1 = __last1 - __first1;
|
||||
const size_t __len2 = __last2 - __first2;
|
||||
const int __result = __builtin_memcmp(__first1, __first2,
|
||||
std::min(__len1, __len2));
|
||||
return __result != 0 ? __result < 0 : __len1 < __len2;
|
||||
}
|
||||
/**
|
||||
* @brief Finds the places in ranges which don't match.
|
||||
* @param first1 An input iterator.
|
||||
* @param last1 An input iterator.
|
||||
* @param first2 An input iterator.
|
||||
* @return A pair of iterators pointing to the first mismatch.
|
||||
*
|
||||
* This compares the elements of two ranges using @c == and returns a pair
|
||||
* of iterators. The first iterator points into the first range, the
|
||||
* second iterator points into the second range, and the elements pointed
|
||||
* to by the iterators are not equal.
|
||||
*/
|
||||
template<typename _InputIterator1, typename _InputIterator2>
|
||||
pair<_InputIterator1, _InputIterator2>
|
||||
mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
|
||||
_InputIterator2 __first2)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
|
||||
__glibcxx_function_requires(_EqualOpConcept<
|
||||
typename iterator_traits<_InputIterator1>::value_type,
|
||||
typename iterator_traits<_InputIterator2>::value_type>)
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
|
||||
inline bool
|
||||
lexicographical_compare(const char* __first1, const char* __last1,
|
||||
const char* __first2, const char* __last2)
|
||||
{
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
__glibcxx_requires_valid_range(__first2, __last2);
|
||||
while (__first1 != __last1 && *__first1 == *__first2)
|
||||
{
|
||||
++__first1;
|
||||
++__first2;
|
||||
}
|
||||
return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
|
||||
}
|
||||
|
||||
if (__gnu_cxx::__numeric_traits<char>::__is_signed)
|
||||
return std::lexicographical_compare((const signed char*) __first1,
|
||||
(const signed char*) __last1,
|
||||
(const signed char*) __first2,
|
||||
(const signed char*) __last2);
|
||||
else
|
||||
return std::lexicographical_compare((const unsigned char*) __first1,
|
||||
(const unsigned char*) __last1,
|
||||
(const unsigned char*) __first2,
|
||||
(const unsigned char*) __last2);
|
||||
}
|
||||
/**
|
||||
* @brief Finds the places in ranges which don't match.
|
||||
* @param first1 An input iterator.
|
||||
* @param last1 An input iterator.
|
||||
* @param first2 An input iterator.
|
||||
* @param binary_pred A binary predicate @link s20_3_1_base
|
||||
* functor@endlink.
|
||||
* @return A pair of iterators pointing to the first mismatch.
|
||||
*
|
||||
* This compares the elements of two ranges using the binary_pred
|
||||
* parameter, and returns a pair
|
||||
* of iterators. The first iterator points into the first range, the
|
||||
* second iterator points into the second range, and the elements pointed
|
||||
* to by the iterators are not equal.
|
||||
*/
|
||||
template<typename _InputIterator1, typename _InputIterator2,
|
||||
typename _BinaryPredicate>
|
||||
pair<_InputIterator1, _InputIterator2>
|
||||
mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
|
||||
_InputIterator2 __first2, _BinaryPredicate __binary_pred)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
|
||||
_GLIBCXX_END_NAMESPACE
|
||||
while (__first1 != __last1 && bool(__binary_pred(*__first1, *__first2)))
|
||||
{
|
||||
++__first1;
|
||||
++__first2;
|
||||
}
|
||||
return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NESTED_NAMESPACE
|
||||
|
||||
// NB: This file is included within many other C++ includes, as a way
|
||||
// of getting the base algorithms. So, make sure that parallel bits
|
||||
// come in too if requested.
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
//# include <parallel/algorithm>
|
||||
# include <parallel/algobase.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -62,7 +62,7 @@
|
||||
#ifndef _STL_BVECTOR_H
|
||||
#define _STL_BVECTOR_H 1
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
typedef unsigned long _Bit_type;
|
||||
enum { _S_word_bit = int(__CHAR_BIT__ * sizeof(_Bit_type)) };
|
||||
@ -432,7 +432,7 @@ _GLIBCXX_END_NESTED_NAMESPACE
|
||||
// Declare a partial specialization of vector<T, Alloc>.
|
||||
#include <bits/stl_vector.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @brief A specialization of vector for booleans which offers fixed time
|
||||
|
@ -66,7 +66,7 @@
|
||||
#include <bits/stl_iterator_base_types.h>
|
||||
#include <bits/stl_iterator_base_funcs.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @if maint
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
// Supporting structures are split into common and templated types; the
|
||||
// latter publicly inherits from the former in an effort to reduce code
|
||||
|
@ -65,7 +65,7 @@
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @brief A standard container made up of (key,value) pairs, which can be
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @brief A standard container made up of (key,value) pairs, which can be
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @brief A standard container made up of elements, which can be retrieved
|
||||
|
@ -65,7 +65,7 @@
|
||||
#include <bits/concept_check.h>
|
||||
#include <debug/debug.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_P)
|
||||
|
||||
/**
|
||||
* @brief Accumulate values in a range.
|
||||
@ -336,6 +336,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
return ++__result;
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE
|
||||
_GLIBCXX_END_NESTED_NAMESPACE
|
||||
|
||||
#endif /* _STL_NUMERIC_H */
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @brief A standard container made up of unique keys, which can be
|
||||
|
@ -66,7 +66,7 @@
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @if maint
|
||||
|
@ -62,7 +62,7 @@
|
||||
#ifndef _VECTOR_TCC
|
||||
#define _VECTOR_TCC 1
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
|
@ -45,10 +45,10 @@ namespace __debug
|
||||
{
|
||||
template<size_t _Nb>
|
||||
class bitset
|
||||
: public _GLIBCXX_STD::bitset<_Nb>,
|
||||
: public _GLIBCXX_STD_D::bitset<_Nb>,
|
||||
public __gnu_debug::_Safe_sequence_base
|
||||
{
|
||||
typedef _GLIBCXX_STD::bitset<_Nb> _Base;
|
||||
typedef _GLIBCXX_STD_D::bitset<_Nb> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence_base _Safe_base;
|
||||
|
||||
public:
|
||||
|
@ -113,6 +113,7 @@ namespace std
|
||||
#else
|
||||
# define _GLIBCXX_DEBUG_PEDASSERT(_Condition)
|
||||
#endif
|
||||
|
||||
# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement
|
||||
|
||||
# define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg)
|
||||
|
@ -45,10 +45,10 @@ namespace __debug
|
||||
{
|
||||
template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
|
||||
class deque
|
||||
: public _GLIBCXX_STD::deque<_Tp, _Allocator>,
|
||||
: public _GLIBCXX_STD_D::deque<_Tp, _Allocator>,
|
||||
public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
|
||||
{
|
||||
typedef _GLIBCXX_STD::deque<_Tp, _Allocator> _Base;
|
||||
typedef _GLIBCXX_STD_D::deque<_Tp, _Allocator> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence<deque> _Safe_base;
|
||||
|
||||
public:
|
||||
|
@ -73,10 +73,10 @@ namespace __debug
|
||||
{
|
||||
template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
|
||||
class list
|
||||
: public _GLIBCXX_STD::list<_Tp, _Allocator>,
|
||||
: public _GLIBCXX_STD_D::list<_Tp, _Allocator>,
|
||||
public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
|
||||
{
|
||||
typedef _GLIBCXX_STD::list<_Tp, _Allocator> _Base;
|
||||
typedef _GLIBCXX_STD_D::list<_Tp, _Allocator> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence<list> _Safe_base;
|
||||
|
||||
public:
|
||||
|
@ -46,10 +46,10 @@ namespace __debug
|
||||
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
|
||||
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
|
||||
class map
|
||||
: public _GLIBCXX_STD::map<_Key, _Tp, _Compare, _Allocator>,
|
||||
: public _GLIBCXX_STD_D::map<_Key, _Tp, _Compare, _Allocator>,
|
||||
public __gnu_debug::_Safe_sequence<map<_Key, _Tp, _Compare, _Allocator> >
|
||||
{
|
||||
typedef _GLIBCXX_STD::map<_Key, _Tp, _Compare, _Allocator> _Base;
|
||||
typedef _GLIBCXX_STD_D::map<_Key, _Tp, _Compare, _Allocator> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence<map> _Safe_base;
|
||||
|
||||
public:
|
||||
|
@ -46,10 +46,10 @@ namespace __debug
|
||||
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
|
||||
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
|
||||
class multimap
|
||||
: public _GLIBCXX_STD::multimap<_Key, _Tp, _Compare, _Allocator>,
|
||||
: public _GLIBCXX_STD_D::multimap<_Key, _Tp, _Compare, _Allocator>,
|
||||
public __gnu_debug::_Safe_sequence<multimap<_Key,_Tp,_Compare,_Allocator> >
|
||||
{
|
||||
typedef _GLIBCXX_STD::multimap<_Key, _Tp, _Compare, _Allocator> _Base;
|
||||
typedef _GLIBCXX_STD_D::multimap<_Key, _Tp, _Compare, _Allocator> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence<multimap> _Safe_base;
|
||||
|
||||
public:
|
||||
|
@ -46,10 +46,10 @@ namespace __debug
|
||||
template<typename _Key, typename _Compare = std::less<_Key>,
|
||||
typename _Allocator = std::allocator<_Key> >
|
||||
class multiset
|
||||
: public _GLIBCXX_STD::multiset<_Key, _Compare, _Allocator>,
|
||||
: public _GLIBCXX_STD_D::multiset<_Key, _Compare, _Allocator>,
|
||||
public __gnu_debug::_Safe_sequence<multiset<_Key, _Compare, _Allocator> >
|
||||
{
|
||||
typedef _GLIBCXX_STD::multiset<_Key, _Compare, _Allocator> _Base;
|
||||
typedef _GLIBCXX_STD_D::multiset<_Key, _Compare, _Allocator> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence<multiset> _Safe_base;
|
||||
|
||||
public:
|
||||
|
@ -46,10 +46,10 @@ namespace __debug
|
||||
template<typename _Key, typename _Compare = std::less<_Key>,
|
||||
typename _Allocator = std::allocator<_Key> >
|
||||
class set
|
||||
: public _GLIBCXX_STD::set<_Key,_Compare,_Allocator>,
|
||||
: public _GLIBCXX_STD_D::set<_Key,_Compare,_Allocator>,
|
||||
public __gnu_debug::_Safe_sequence<set<_Key, _Compare, _Allocator> >
|
||||
{
|
||||
typedef _GLIBCXX_STD::set<_Key,_Compare,_Allocator> _Base;
|
||||
typedef _GLIBCXX_STD_D::set<_Key,_Compare,_Allocator> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence<set> _Safe_base;
|
||||
|
||||
public:
|
||||
|
@ -47,10 +47,10 @@ namespace __debug
|
||||
template<typename _Tp,
|
||||
typename _Allocator = std::allocator<_Tp> >
|
||||
class vector
|
||||
: public _GLIBCXX_STD::vector<_Tp, _Allocator>,
|
||||
: public _GLIBCXX_STD_D::vector<_Tp, _Allocator>,
|
||||
public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
|
||||
{
|
||||
typedef _GLIBCXX_STD::vector<_Tp, _Allocator> _Base;
|
||||
typedef _GLIBCXX_STD_D::vector<_Tp, _Allocator> _Base;
|
||||
typedef __gnu_debug::_Safe_sequence<vector> _Safe_base;
|
||||
|
||||
typedef typename _Base::const_iterator _Base_const_iterator;
|
||||
|
@ -65,7 +65,7 @@
|
||||
#include <ext/hashtable.h>
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(__gnu_cxx, _GLIBCXX_EXT)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(__gnu_cxx, _GLIBCXX_EXT_D)
|
||||
|
||||
using std::equal_to;
|
||||
using std::allocator;
|
||||
|
@ -65,7 +65,7 @@
|
||||
#include <ext/hashtable.h>
|
||||
#include <bits/concept_check.h>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(__gnu_cxx, _GLIBCXX_EXT)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(__gnu_cxx, _GLIBCXX_EXT_D)
|
||||
|
||||
using std::equal_to;
|
||||
using std::allocator;
|
||||
|
1585
libstdc++-v3/include/parallel/algo.h
Normal file
1585
libstdc++-v3/include/parallel/algo.h
Normal file
File diff suppressed because it is too large
Load Diff
256
libstdc++-v3/include/parallel/algobase.h
Normal file
256
libstdc++-v3/include/parallel/algobase.h
Normal file
@ -0,0 +1,256 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/algobase.h
|
||||
* @brief Parallel STL function calls corresponding to the
|
||||
* stl_algobase.h header. The functions defined here mainly do case
|
||||
* switches and call the actual parallelized versions in other files.
|
||||
* Inlining policy: Functions that basically only contain one
|
||||
* function call, are declared inline.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler and Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_ALGOBASE_H
|
||||
#define _GLIBCXX_PARALLEL_ALGOBASE_H 1
|
||||
|
||||
#include <parallel/algorithmfwd.h>
|
||||
#include <bits/stl_algobase.h>
|
||||
#include <parallel/base.h>
|
||||
#include <parallel/tags.h>
|
||||
#include <parallel/settings.h>
|
||||
#include <parallel/find.h>
|
||||
#include <parallel/find_selectors.h>
|
||||
#include <parallel/for_each.h>
|
||||
#include <parallel/for_each_selectors.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace __parallel
|
||||
{
|
||||
// Sequential fallback
|
||||
template<typename InputIterator1, typename InputIterator2>
|
||||
inline bool
|
||||
equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, __gnu_parallel::sequential_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::equal<InputIterator1, InputIterator2>(begin1, end1, begin2);
|
||||
}
|
||||
|
||||
// Sequential fallback
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate>
|
||||
inline bool
|
||||
equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, Predicate pred, __gnu_parallel::sequential_tag)
|
||||
{ return _GLIBCXX_STD_P::equal(begin1, end1, begin2, pred); }
|
||||
|
||||
// Public interface
|
||||
template<typename InputIterator1, typename InputIterator2>
|
||||
inline bool
|
||||
equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
|
||||
{ return mismatch(begin1, end1, begin2).first == end1; }
|
||||
|
||||
// Public interface
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate>
|
||||
inline bool
|
||||
equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, Predicate pred)
|
||||
{ return mismatch(begin1, end1, begin2, pred).first == end1; }
|
||||
|
||||
// NB: lexicographical_compare equires mismatch.
|
||||
|
||||
// Sequential fallback
|
||||
template<typename InputIterator1, typename InputIterator2>
|
||||
inline pair<InputIterator1, InputIterator2>
|
||||
mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, __gnu_parallel::sequential_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::mismatch<InputIterator1, InputIterator2>(begin1, end1, begin2);
|
||||
}
|
||||
|
||||
// Sequential fallback
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate>
|
||||
inline pair<InputIterator1, InputIterator2>
|
||||
mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, Predicate pred, __gnu_parallel::sequential_tag)
|
||||
{ return _GLIBCXX_STD_P::mismatch(begin1, end1, begin2, pred); }
|
||||
|
||||
// Sequential fallback for input iterator case
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate, typename IteratorTag1, typename IteratorTag2>
|
||||
inline pair<InputIterator1, InputIterator2>
|
||||
mismatch_switch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, Predicate pred, IteratorTag1, IteratorTag2)
|
||||
{ return _GLIBCXX_STD_P::mismatch(begin1, end1, begin2, pred); }
|
||||
|
||||
// Parallel mismatch for random access iterators
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Predicate>
|
||||
pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
mismatch_switch(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, Predicate pred, random_access_iterator_tag, random_access_iterator_tag)
|
||||
{
|
||||
if (_GLIBCXX_PARALLEL_CONDITION(true))
|
||||
{
|
||||
RandomAccessIterator1 res_first =
|
||||
__gnu_parallel::find_template(begin1, end1, begin2, pred, __gnu_parallel::mismatch_selector()).first;
|
||||
return make_pair(res_first, begin2 + (res_first - begin1));
|
||||
}
|
||||
else
|
||||
return _GLIBCXX_STD_P::mismatch(begin1, end1, begin2, pred);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
template<typename InputIterator1, typename InputIterator2>
|
||||
inline pair<InputIterator1, InputIterator2>
|
||||
mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
|
||||
{
|
||||
typedef std::iterator_traits<InputIterator1> iterator1_traits;
|
||||
typedef std::iterator_traits<InputIterator2> iterator2_traits;
|
||||
typedef typename iterator1_traits::value_type value1_type;
|
||||
typedef typename iterator2_traits::value_type value2_type;
|
||||
typedef typename iterator1_traits::iterator_category iterator1_category;
|
||||
typedef typename iterator2_traits::iterator_category iterator2_category;
|
||||
|
||||
return mismatch_switch(begin1, end1, begin2, __gnu_parallel::equal_to<value1_type, value2_type>(), iterator1_category(), iterator2_category());
|
||||
}
|
||||
|
||||
// Public interface
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate>
|
||||
inline pair<InputIterator1, InputIterator2>
|
||||
mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
|
||||
Predicate pred)
|
||||
{
|
||||
typedef std::iterator_traits<InputIterator1> iterator1_traits;
|
||||
typedef std::iterator_traits<InputIterator2> iterator2_traits;
|
||||
typedef typename iterator1_traits::iterator_category iterator1_category;
|
||||
typedef typename iterator2_traits::iterator_category iterator2_category;
|
||||
|
||||
return mismatch_switch(begin1, end1, begin2, pred, iterator1_category(), iterator2_category());
|
||||
}
|
||||
|
||||
// Sequential fallback
|
||||
template<typename InputIterator1, typename InputIterator2>
|
||||
inline bool
|
||||
lexicographical_compare(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, __gnu_parallel::sequential_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::lexicographical_compare<InputIterator1, InputIterator2>(begin1, end1, begin2, end2);
|
||||
}
|
||||
|
||||
// Sequential fallback
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate>
|
||||
inline bool
|
||||
lexicographical_compare(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, Predicate pred, __gnu_parallel::sequential_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::lexicographical_compare(begin1, end1, begin2, end2, pred);
|
||||
}
|
||||
|
||||
// Sequential fallback for input iterator case
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate, typename IteratorTag1, typename IteratorTag2>
|
||||
inline bool
|
||||
lexicographical_compare_switch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, Predicate pred, IteratorTag1, IteratorTag2)
|
||||
{
|
||||
return _GLIBCXX_STD_P::lexicographical_compare(begin1, end1, begin2, end2, pred);
|
||||
}
|
||||
|
||||
// Parallel lexicographical_compare for random access iterators
|
||||
// Limitation: Both valuetypes must be the same
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Predicate>
|
||||
bool
|
||||
lexicographical_compare_switch(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, RandomAccessIterator2 end2, Predicate pred, random_access_iterator_tag, random_access_iterator_tag)
|
||||
{
|
||||
if (_GLIBCXX_PARALLEL_CONDITION(true))
|
||||
{
|
||||
typedef iterator_traits<RandomAccessIterator1> traits1_type;
|
||||
typedef typename traits1_type::value_type value1_type;
|
||||
|
||||
typedef iterator_traits<RandomAccessIterator2> traits2_type;
|
||||
typedef typename traits2_type::value_type value2_type;
|
||||
|
||||
typedef __gnu_parallel::equal_from_less<Predicate, value1_type, value2_type> equal_type;
|
||||
|
||||
// Longer sequence in first place.
|
||||
if ((end1 - begin1) < (end2 - begin2))
|
||||
{
|
||||
typedef pair<RandomAccessIterator1, RandomAccessIterator2> pair_type;
|
||||
pair_type mm = mismatch_switch(begin1, end1, begin2, equal_type(pred), random_access_iterator_tag(), random_access_iterator_tag());
|
||||
|
||||
// Less because shorter.
|
||||
const bool lbs = mm.first == end1;
|
||||
|
||||
// Less because differing elements less.
|
||||
const bool lbdel = pred(*mm.first, *mm.second);
|
||||
|
||||
return lbs || lbdel;
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef pair<RandomAccessIterator2, RandomAccessIterator1> pair_type;
|
||||
pair_type mm = mismatch_switch(begin2, end2, begin1, equal_type(pred), random_access_iterator_tag(), random_access_iterator_tag());
|
||||
|
||||
// Less because shorter.
|
||||
const bool lbs = mm.first != end2;
|
||||
|
||||
// Less because differing element less.
|
||||
const bool lbdel = pred(*mm.second, *mm.first);
|
||||
|
||||
return lbs && lbdel;
|
||||
}
|
||||
}
|
||||
else
|
||||
return _GLIBCXX_STD_P::lexicographical_compare(begin1, end1, begin2, end2, pred);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
template<typename InputIterator1, typename InputIterator2>
|
||||
inline bool
|
||||
lexicographical_compare(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2)
|
||||
{
|
||||
typedef iterator_traits<InputIterator1> traits1_type;
|
||||
typedef typename traits1_type::value_type value1_type;
|
||||
typedef typename traits1_type::iterator_category iterator1_category;
|
||||
|
||||
typedef iterator_traits<InputIterator2> traits2_type;
|
||||
typedef typename traits2_type::value_type value2_type;
|
||||
typedef typename traits2_type::iterator_category iterator2_category;
|
||||
typedef __gnu_parallel::less<value1_type, value2_type> less_type;
|
||||
|
||||
return lexicographical_compare_switch(begin1, end1, begin2, end2, less_type(), iterator1_category(), iterator2_category());
|
||||
}
|
||||
|
||||
// Public interface
|
||||
template<typename InputIterator1, typename InputIterator2, typename Predicate>
|
||||
inline bool
|
||||
lexicographical_compare(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2, InputIterator2 end2, Predicate pred)
|
||||
{
|
||||
typedef iterator_traits<InputIterator1> traits1_type;
|
||||
typedef typename traits1_type::iterator_category iterator1_category;
|
||||
|
||||
typedef iterator_traits<InputIterator2> traits2_type;
|
||||
typedef typename traits2_type::iterator_category iterator2_category;
|
||||
|
||||
return lexicographical_compare_switch(begin1, end1, begin2, end2, pred, iterator1_category(), iterator2_category());
|
||||
}
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif /* _GLIBCXX_ALGOBASE_H */
|
45
libstdc++-v3/include/parallel/algorithm
Normal file
45
libstdc++-v3/include/parallel/algorithm
Normal file
@ -0,0 +1,45 @@
|
||||
// Algorithm extensions -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007
|
||||
// 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING. If not, write to the Free
|
||||
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
// USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free software
|
||||
// library without restriction. Specifically, if other files instantiate
|
||||
// templates or use macros or inline functions from this file, or you compile
|
||||
// this file and link it with other files to produce an executable, this
|
||||
// file does not by itself cause the resulting executable to be covered by
|
||||
// the GNU General Public License. This exception does not however
|
||||
// invalidate any other reasons why the executable file might be covered by
|
||||
// the GNU General Public License.
|
||||
|
||||
/** @file parallel/algorithm
|
||||
* This file is a GNU extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _PARALLEL_ALGORITHM
|
||||
#define _PARALLEL_ALGORITHM 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <algorithm>
|
||||
#include <parallel/algorithmfwd.h>
|
||||
#include <parallel/algobase.h>
|
||||
#include <parallel/algo.h>
|
||||
|
||||
#endif
|
719
libstdc++-v3/include/parallel/algorithmfwd.h
Normal file
719
libstdc++-v3/include/parallel/algorithmfwd.h
Normal file
@ -0,0 +1,719 @@
|
||||
// <algorithm> parallel extensions -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/algorithmfwd.h
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_ALGORITHMFWD_H
|
||||
#define _GLIBCXX_PARALLEL_ALGORITHMFWD_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <parallel/tags.h>
|
||||
#include <parallel/settings.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace __parallel
|
||||
{
|
||||
template<typename _FIter>
|
||||
inline _FIter
|
||||
adjacent_find(_FIter, _FIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename BinaryPredicate>
|
||||
inline _FIter
|
||||
adjacent_find(_FIter, _FIter, BinaryPredicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter>
|
||||
inline _FIter
|
||||
adjacent_find(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename BinaryPredicate>
|
||||
inline _FIter
|
||||
adjacent_find(_FIter, _FIter, BinaryPredicate);
|
||||
|
||||
template<typename _RAIter>
|
||||
_RAIter
|
||||
adjacent_find_switch(_RAIter, _RAIter, random_access_iterator_tag);
|
||||
|
||||
template<typename _FIter, typename IteratorTag>
|
||||
inline _FIter
|
||||
adjacent_find_switch(_FIter, _FIter, IteratorTag);
|
||||
|
||||
template<typename _FIter, typename BinaryPredicate, typename IteratorTag>
|
||||
inline _FIter
|
||||
adjacent_find_switch(_FIter, _FIter, BinaryPredicate, IteratorTag);
|
||||
|
||||
template<typename _RAIter, typename BinaryPredicate>
|
||||
_RAIter
|
||||
adjacent_find_switch(_RAIter, _RAIter, BinaryPredicate, random_access_iterator_tag);
|
||||
|
||||
|
||||
template<typename _IIter, typename T>
|
||||
inline typename iterator_traits<_IIter>::difference_type
|
||||
count(_IIter, _IIter, const T& value, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename T>
|
||||
inline typename iterator_traits<_IIter>::difference_type
|
||||
count(_IIter, _IIter, const T& value, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced);
|
||||
|
||||
template<typename _RAIter, typename T>
|
||||
typename iterator_traits<_RAIter>::difference_type
|
||||
count_switch(_RAIter, _RAIter, const T& value, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _IIter, typename T, typename IteratorTag>
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count_switch(_IIter, _IIter, const T& value, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
|
||||
template<typename _IIter, typename Predicate>
|
||||
inline typename iterator_traits<_IIter>::difference_type
|
||||
count_if(_IIter, _IIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename Predicate>
|
||||
inline typename iterator_traits<_IIter>::difference_type
|
||||
count_if(_IIter, _IIter, Predicate, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced);
|
||||
|
||||
template<typename _RAIter, typename Predicate>
|
||||
typename iterator_traits<_RAIter>::difference_type
|
||||
count_if_switch(_RAIter, _RAIter, Predicate, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _IIter, typename Predicate, typename IteratorTag>
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count_if_switch(_IIter, _IIter, Predicate, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
// algobase.h
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
inline bool
|
||||
equal(_IIter1, _IIter1, _IIter2, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate>
|
||||
inline bool
|
||||
equal(_IIter1, _IIter1, _IIter2, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
inline bool
|
||||
equal(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate>
|
||||
inline bool
|
||||
equal(_IIter1, _IIter1, _IIter2, Predicate);
|
||||
|
||||
template<typename _IIter, typename T>
|
||||
inline _IIter
|
||||
find(_IIter, _IIter, const T&, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename T>
|
||||
inline _IIter
|
||||
find(_IIter, _IIter, const T& val);
|
||||
|
||||
template<typename _IIter, typename T, typename IteratorTag>
|
||||
inline _IIter
|
||||
find_switch(_IIter, _IIter, const T&, IteratorTag);
|
||||
|
||||
template<typename _RAIter, typename T>
|
||||
_RAIter
|
||||
find_switch(_RAIter, _RAIter, const T&, random_access_iterator_tag);
|
||||
|
||||
template<typename _IIter, typename Predicate>
|
||||
inline _IIter
|
||||
find_if(_IIter, _IIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename Predicate>
|
||||
inline _IIter
|
||||
find_if (_IIter, _IIter, Predicate);
|
||||
|
||||
template<typename _IIter, typename Predicate, typename IteratorTag>
|
||||
inline _IIter
|
||||
find_if_switch(_IIter, _IIter, Predicate, IteratorTag);
|
||||
|
||||
template<typename _RAIter, typename Predicate>
|
||||
_RAIter
|
||||
find_if_switch(_RAIter, _RAIter, Predicate, random_access_iterator_tag);
|
||||
|
||||
template<typename _IIter, typename _FIter>
|
||||
inline _IIter
|
||||
find_first_of(_IIter, _IIter, _FIter, _FIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _FIter, typename BinaryPredicate>
|
||||
inline _IIter
|
||||
find_first_of(_IIter, _IIter, _FIter, _FIter, BinaryPredicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _FIter, typename BinaryPredicate>
|
||||
inline _IIter
|
||||
find_first_of(_IIter, _IIter, _FIter, _FIter, BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _FIter>
|
||||
_IIter
|
||||
find_first_of(_IIter, _IIter, _FIter, _FIter);
|
||||
|
||||
template<typename _IIter, typename _FIter, typename IteratorTag1, typename IteratorTag2>
|
||||
inline _IIter
|
||||
find_first_of_switch(_IIter, _IIter, _FIter, _FIter, IteratorTag1, IteratorTag2);
|
||||
|
||||
template<typename _RAIter, typename _FIter, typename BinaryPredicate, typename IteratorTag>
|
||||
inline _RAIter
|
||||
find_first_of_switch(_RAIter, _RAIter, _FIter, _FIter, BinaryPredicate, random_access_iterator_tag, IteratorTag);
|
||||
|
||||
template<typename _IIter, typename _FIter, typename BinaryPredicate, typename IteratorTag1, typename IteratorTag2>
|
||||
inline _IIter
|
||||
find_first_of_switch(_IIter, _IIter, _FIter, _FIter, BinaryPredicate, IteratorTag1, IteratorTag2);
|
||||
|
||||
|
||||
template<typename _IIter, typename Function>
|
||||
inline Function
|
||||
for_each(_IIter, _IIter, Function f, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename Iterator, typename Function>
|
||||
inline Function
|
||||
for_each(Iterator, Iterator, Function f, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _IIter, typename Function, typename IteratorTag>
|
||||
Function
|
||||
for_each_switch(_IIter, _IIter, Function f, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter, typename Function>
|
||||
Function
|
||||
for_each_switch(_RAIter, _RAIter, Function f, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _FIter, typename Generator>
|
||||
inline void
|
||||
generate(_FIter, _FIter, Generator, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename Generator>
|
||||
inline void
|
||||
generate(_FIter, _FIter, Generator, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _FIter, typename Generator, typename IteratorTag>
|
||||
void
|
||||
generate_switch(_FIter, _FIter, Generator, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter, typename Generator>
|
||||
void
|
||||
generate_switch(_RAIter, _RAIter, Generator, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _OIter, typename Size, typename Generator>
|
||||
inline _OIter
|
||||
generate_n(_OIter, Size, Generator, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _OIter, typename Size, typename Generator>
|
||||
inline _OIter
|
||||
generate_n(_OIter, Size, Generator, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _OIter, typename Size, typename Generator, typename IteratorTag>
|
||||
_OIter
|
||||
generate_n_switch(_OIter, Size, Generator, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter, typename Size, typename Generator>
|
||||
_RAIter
|
||||
generate_n_switch(_RAIter, Size, Generator, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
inline bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate>
|
||||
inline bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
inline bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate>
|
||||
inline bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate, typename IteratorTag1, typename IteratorTag2>
|
||||
inline bool
|
||||
lexicographical_compare_switch(_IIter1, _IIter1, _IIter2, _IIter2, Predicate, IteratorTag1, IteratorTag2);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename Predicate>
|
||||
bool
|
||||
lexicographical_compare_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter2, Predicate, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
// algo.h
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
inline pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate>
|
||||
inline pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
inline pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate>
|
||||
inline pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2, Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate, typename IteratorTag1, typename IteratorTag2>
|
||||
inline pair<_IIter1, _IIter2>
|
||||
mismatch_switch(_IIter1, _IIter1, _IIter2, Predicate, IteratorTag1, IteratorTag2);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename Predicate>
|
||||
pair<_RAIter1, _RAIter2>
|
||||
mismatch_switch(_RAIter1, _RAIter1, _RAIter2, Predicate, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
inline _FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
inline _FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename BinaryPredicate>
|
||||
inline _FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2, BinaryPredicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename BinaryPredicate>
|
||||
inline _FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2, BinaryPredicate);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2>
|
||||
_RAIter1
|
||||
search_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter2, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename IteratorTag1, typename IteratorTag2>
|
||||
inline _FIter1
|
||||
search_switch(_FIter1, _FIter1, _FIter2, _FIter2, IteratorTag1, IteratorTag2);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename BinaryPredicate>
|
||||
_RAIter1
|
||||
search_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter2, BinaryPredicate , random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename BinaryPredicate, typename IteratorTag1, typename IteratorTag2>
|
||||
inline _FIter1
|
||||
search_switch(_FIter1, _FIter1, _FIter2, _FIter2, BinaryPredicate, IteratorTag1, IteratorTag2);
|
||||
|
||||
template<typename _FIter, typename Integer, typename T>
|
||||
inline _FIter
|
||||
search_n(_FIter, _FIter, Integer, const T&, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename Integer, typename T, typename BinaryPredicate>
|
||||
inline _FIter
|
||||
search_n(_FIter, _FIter, Integer, const T&, BinaryPredicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename Integer, typename T>
|
||||
inline _FIter
|
||||
search_n(_FIter, _FIter, Integer, const T& val);
|
||||
|
||||
template<typename _FIter, typename Integer, typename T, typename BinaryPredicate>
|
||||
inline _FIter
|
||||
search_n(_FIter, _FIter, Integer, const T&, BinaryPredicate);
|
||||
|
||||
template<typename _RAIter, typename Integer, typename T, typename BinaryPredicate>
|
||||
_RAIter
|
||||
search_n_switch(_RAIter, _RAIter, Integer, const T&, BinaryPredicate, random_access_iterator_tag);
|
||||
|
||||
template<typename _FIter, typename Integer, typename T, typename BinaryPredicate, typename IteratorTag>
|
||||
inline _FIter
|
||||
search_n_switch(_FIter, _FIter, Integer, const T&, BinaryPredicate, IteratorTag);
|
||||
|
||||
|
||||
template<typename _IIter, typename _OIter, typename UnaryOperation>
|
||||
inline _OIter
|
||||
transform(_IIter, _IIter, _OIter, UnaryOperation, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename BinaryOperation>
|
||||
inline _OIter
|
||||
transform(_IIter1, _IIter1, _IIter2, _OIter, BinaryOperation binary_op, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename UnaryOperation>
|
||||
inline _OIter
|
||||
transform(_IIter, _IIter, _OIter, UnaryOperation, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename BinaryOperation>
|
||||
inline _OIter
|
||||
transform(_IIter1, _IIter1, _IIter2, _OIter, BinaryOperation binary_op, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter3, typename UnaryOperation>
|
||||
_RAIter3
|
||||
transform1_switch(_RAIter1, _RAIter1, _RAIter3, UnaryOperation, random_access_iterator_tag, random_access_iterator_tag, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter3, typename UnaryOperation, typename IteratorTag1, typename IteratorTag2>
|
||||
inline _RAIter3
|
||||
transform1_switch(_RAIter1, _RAIter1, _RAIter3, UnaryOperation, IteratorTag1, IteratorTag2, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename _RAIter3, typename BinaryOperation>
|
||||
_RAIter3
|
||||
transform2_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter3, BinaryOperation binary_op, random_access_iterator_tag, random_access_iterator_tag, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename _RAIter3, typename BinaryOperation, typename tag1, typename tag2, typename tag3>
|
||||
inline _RAIter3
|
||||
transform2_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter3, BinaryOperation binary_op, tag1, tag2, tag3, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _FIter, typename T>
|
||||
inline void
|
||||
replace(_FIter, _FIter, const T&, const T&, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename T>
|
||||
inline void
|
||||
replace(_FIter, _FIter, const T&, const T&, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _FIter, typename T, typename IteratorTag>
|
||||
void
|
||||
replace_switch(_FIter, _FIter, const T&, const T&, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter, typename T>
|
||||
void
|
||||
replace_switch(_RAIter, _RAIter, const T&, const T&, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
|
||||
template<typename _FIter, typename Predicate, typename T>
|
||||
inline void
|
||||
replace_if(_FIter, _FIter, Predicate, const T&, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename Predicate, typename T>
|
||||
inline void
|
||||
replace_if(_FIter, _FIter, Predicate, const T&, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _FIter, typename Predicate, typename T, typename IteratorTag>
|
||||
void
|
||||
replace_if_switch(_FIter, _FIter, Predicate, const T&, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter, typename Predicate, typename T>
|
||||
void
|
||||
replace_if_switch(_RAIter, _RAIter, Predicate, const T&, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _FIter>
|
||||
inline _FIter
|
||||
max_element(_FIter, _FIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
inline _FIter
|
||||
max_element(_FIter, _FIter, _Compare, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter>
|
||||
inline _FIter
|
||||
max_element(_FIter, _FIter, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
inline _FIter
|
||||
max_element(_FIter, _FIter, _Compare, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _FIter, typename _Compare, typename IteratorTag>
|
||||
_FIter
|
||||
max_element_switch(_FIter, _FIter, _Compare, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_RAIter
|
||||
max_element_switch(_RAIter, _RAIter, _Compare, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare>
|
||||
inline _OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare>
|
||||
inline _OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare, typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
|
||||
inline _OIter
|
||||
merge_switch(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare, IteratorTag1, IteratorTag2, IteratorTag3);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename _Compare>
|
||||
_OIter
|
||||
merge_switch(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare, random_access_iterator_tag, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
template<typename _FIter>
|
||||
inline _FIter
|
||||
min_element(_FIter, _FIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
inline _FIter
|
||||
min_element(_FIter, _FIter, _Compare, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter>
|
||||
inline _FIter
|
||||
min_element(_FIter, _FIter, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
inline _FIter
|
||||
min_element(_FIter, _FIter, _Compare, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _FIter, typename _Compare, typename IteratorTag>
|
||||
_FIter
|
||||
min_element_switch(_FIter, _FIter, _Compare, IteratorTag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_RAIter
|
||||
min_element_switch(_RAIter, _RAIter, _Compare, random_access_iterator_tag, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _RAIter>
|
||||
inline void
|
||||
nth_element(_RAIter, _RAIter, _RAIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter, _Compare, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
inline void
|
||||
nth_element(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter, _Compare, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _FIter, typename Predicate>
|
||||
inline _FIter
|
||||
partition(_FIter, _FIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _FIter, typename Predicate>
|
||||
inline _FIter
|
||||
partition(_FIter, _FIter, Predicate);
|
||||
|
||||
template<typename _FIter, typename Predicate, typename IteratorTag>
|
||||
inline _FIter
|
||||
partition_switch(_FIter, _FIter, Predicate, IteratorTag);
|
||||
|
||||
template<typename _RAIter, typename Predicate>
|
||||
_RAIter
|
||||
partition_switch(_RAIter, _RAIter, Predicate, random_access_iterator_tag);
|
||||
|
||||
template<typename _RAIter>
|
||||
inline void
|
||||
random_shuffle(_RAIter, _RAIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter, typename RandomNumberGenerator>
|
||||
inline void
|
||||
random_shuffle(_RAIter, _RAIter, RandomNumberGenerator& rand, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter>
|
||||
inline void
|
||||
random_shuffle(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename RandomNumberGenerator>
|
||||
void
|
||||
random_shuffle(_RAIter, _RAIter, RandomNumberGenerator& rand);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate, typename _OIter, typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
|
||||
inline _OIter
|
||||
set_union_switch(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, IteratorTag1, IteratorTag2, IteratorTag3);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename Output_RAIter, typename Predicate>
|
||||
Output_RAIter
|
||||
set_union_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter2, Output_RAIter, Predicate, random_access_iterator_tag, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate, typename _OIter, typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
|
||||
inline _OIter
|
||||
set_intersection_switch(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, IteratorTag1, IteratorTag2, IteratorTag3);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename Output_RAIter, typename Predicate>
|
||||
Output_RAIter
|
||||
set_intersection_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter2, Output_RAIter, Predicate, random_access_iterator_tag, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate, typename _OIter, typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
|
||||
inline _OIter
|
||||
set_symmetric_difference_switch(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, IteratorTag1, IteratorTag2, IteratorTag3);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename Output_RAIter, typename Predicate>
|
||||
Output_RAIter
|
||||
set_symmetric_difference_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter2, Output_RAIter, Predicate, random_access_iterator_tag, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
inline _OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename Predicate, typename _OIter, typename IteratorTag1, typename IteratorTag2, typename IteratorTag3>
|
||||
inline _OIter
|
||||
set_difference_switch(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, Predicate, IteratorTag1, IteratorTag2, IteratorTag3);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename Output_RAIter, typename Predicate>
|
||||
Output_RAIter
|
||||
set_difference_switch(_RAIter1, _RAIter1, _RAIter2, _RAIter2, Output_RAIter, Predicate, random_access_iterator_tag, random_access_iterator_tag, random_access_iterator_tag);
|
||||
|
||||
|
||||
template<typename _RAIter>
|
||||
inline void
|
||||
sort(_RAIter, _RAIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
inline void
|
||||
sort(_RAIter, _RAIter, _Compare, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter>
|
||||
inline void
|
||||
sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
inline void
|
||||
stable_sort(_RAIter, _RAIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
inline void
|
||||
stable_sort(_RAIter, _RAIter, _Compare, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
inline _OIter
|
||||
unique_copy(_IIter, _IIter, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
unique_copy(_IIter, _IIter, _OIter, Predicate, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
inline _OIter
|
||||
unique_copy(_IIter, _IIter, _OIter);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename Predicate>
|
||||
inline _OIter
|
||||
unique_copy(_IIter, _IIter, _OIter, Predicate);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename Predicate, typename IteratorTag1, typename IteratorTag2>
|
||||
inline _OIter
|
||||
unique_copy_switch(_IIter, _IIter, _OIter, Predicate, IteratorTag1, IteratorTag2);
|
||||
|
||||
template<typename _RAIter, typename RandomAccess_OIter, typename Predicate>
|
||||
RandomAccess_OIter
|
||||
unique_copy_switch(_RAIter, _RAIter, RandomAccess_OIter, Predicate, random_access_iterator_tag, random_access_iterator_tag);
|
||||
} // end namespace __parallel
|
||||
} // end namespace std
|
||||
|
||||
// NB: cannot use _GLIBCXX_STD_P directly here, as it is both scoped
|
||||
// (std::__norm) and unscoped (std::).
|
||||
namespace __gnu_sequential
|
||||
{
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
using std::__norm::partition;
|
||||
using std::__norm::sort;
|
||||
using std::__norm::stable_sort;
|
||||
using std::__norm::random_shuffle;
|
||||
#else
|
||||
using std::partition;
|
||||
using std::sort;
|
||||
using std::stable_sort;
|
||||
using std::random_shuffle;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
451
libstdc++-v3/include/parallel/balanced_quicksort.h
Normal file
451
libstdc++-v3/include/parallel/balanced_quicksort.h
Normal file
@ -0,0 +1,451 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/balanced_quicksort.h
|
||||
* @brief Implementation of a dynamically load-balanced parallel quicksort.
|
||||
*
|
||||
* It works in-place and needs only logarithmic extra memory.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_BAL_QUICKSORT_H
|
||||
#define _GLIBCXX_PARALLEL_BAL_QUICKSORT_H 1
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <bits/stl_algo.h>
|
||||
|
||||
#include <parallel/settings.h>
|
||||
#include <parallel/partition.h>
|
||||
#include <parallel/random_number.h>
|
||||
#include <parallel/queue.h>
|
||||
#include <functional>
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
#include <parallel/checkers.h>
|
||||
#endif
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @brief Information local to one thread in the parallel quicksort run. */
|
||||
template<typename RandomAccessIterator>
|
||||
struct QSBThreadLocal
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
/** @brief Continuous part of the sequence, described by an
|
||||
iterator pair. */
|
||||
typedef std::pair<RandomAccessIterator, RandomAccessIterator> Piece;
|
||||
|
||||
/** @brief Initial piece to work on. */
|
||||
Piece initial;
|
||||
|
||||
/** @brief Work-stealing queue. */
|
||||
RestrictedBoundedConcurrentQueue<Piece> leftover_parts;
|
||||
|
||||
/** @brief Number of threads involved in this algorithm. */
|
||||
thread_index_t num_threads;
|
||||
|
||||
/** @brief Pointer to a counter of elements left over to sort. */
|
||||
volatile difference_type* elements_leftover;
|
||||
|
||||
/** @brief The complete sequence to sort. */
|
||||
Piece global;
|
||||
|
||||
/** @brief Constructor.
|
||||
* @param queue_size Size of the work-stealing queue. */
|
||||
QSBThreadLocal(int queue_size) : leftover_parts(queue_size) { }
|
||||
};
|
||||
|
||||
/** @brief Initialize the thread local storage.
|
||||
* @param tls Array of thread-local storages.
|
||||
* @param queue_size Size of the work-stealing queue. */
|
||||
template<typename RandomAccessIterator>
|
||||
inline void
|
||||
qsb_initialize(QSBThreadLocal<RandomAccessIterator>** tls, int queue_size)
|
||||
{
|
||||
int iam = omp_get_thread_num();
|
||||
tls[iam] = new QSBThreadLocal<RandomAccessIterator>(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 RandomAccessIterator, typename Comparator>
|
||||
inline typename std::iterator_traits<RandomAccessIterator>::difference_type
|
||||
qsb_divide(RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Comparator comp, int num_threads)
|
||||
{
|
||||
_GLIBCXX_PARALLEL_ASSERT(num_threads > 0);
|
||||
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
RandomAccessIterator pivot_pos = median_of_three_iterators(begin, begin + (end - begin) / 2, end - 1, comp);
|
||||
|
||||
#if defined(_GLIBCXX_ASSERTIONS)
|
||||
// Must be in between somewhere.
|
||||
difference_type n = end - begin;
|
||||
|
||||
_GLIBCXX_PARALLEL_ASSERT((!comp(*pivot_pos, *begin) && !comp(*(begin + n / 2), *pivot_pos))
|
||||
|| (!comp(*pivot_pos, *begin) && !comp(*end, *pivot_pos))
|
||||
|| (!comp(*pivot_pos, *(begin + n / 2)) && !comp(*begin, *pivot_pos))
|
||||
|| (!comp(*pivot_pos, *(begin + n / 2)) && !comp(*end, *pivot_pos))
|
||||
|| (!comp(*pivot_pos, *end) && !comp(*begin, *pivot_pos))
|
||||
|| (!comp(*pivot_pos, *end) && !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;
|
||||
|
||||
__gnu_parallel::binder2nd<Comparator, value_type, value_type, bool> pred(comp, *pivot_pos);
|
||||
|
||||
// Divide, returning end - begin - 1 in the worst case.
|
||||
difference_type 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;
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
RandomAccessIterator 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 RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
qsb_conquer(QSBThreadLocal<RandomAccessIterator>** tls,
|
||||
RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Comparator comp, thread_index_t iam, thread_index_t num_threads)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
difference_type n = end - begin;
|
||||
|
||||
if (num_threads <= 1 || n < 2)
|
||||
{
|
||||
tls[iam]->initial.first = begin;
|
||||
tls[iam]->initial.second = end;
|
||||
|
||||
qsb_local_sort_with_helping(tls, comp, iam);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Divide step.
|
||||
difference_type split_pos = qsb_divide(begin, end, comp, num_threads);
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_GLIBCXX_PARALLEL_ASSERT(0 <= split_pos && split_pos < (end - begin));
|
||||
#endif
|
||||
|
||||
thread_index_t num_threads_leftside = std::max<thread_index_t>(1, std::min<thread_index_t>(num_threads - 1, split_pos * num_threads / n));
|
||||
|
||||
#pragma omp atomic
|
||||
*tls[iam]->elements_leftover -= (difference_type)1;
|
||||
|
||||
// Conquer step.
|
||||
#pragma omp parallel sections num_threads(2)
|
||||
{
|
||||
#pragma omp section
|
||||
qsb_conquer(tls, begin, begin + split_pos, comp, iam, num_threads_leftside);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
qsb_local_sort_with_helping(QSBThreadLocal<RandomAccessIterator>** tls,
|
||||
Comparator& comp, int iam)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef std::pair<RandomAccessIterator, RandomAccessIterator> Piece;
|
||||
|
||||
QSBThreadLocal<RandomAccessIterator>& tl = *tls[iam];
|
||||
|
||||
difference_type base_case_n = Settings::sort_qsb_base_case_maximal_n;
|
||||
if (base_case_n < 2)
|
||||
base_case_n = 2;
|
||||
thread_index_t num_threads = tl.num_threads;
|
||||
|
||||
// Every thread has its own random number generator.
|
||||
random_number rng(iam + 1);
|
||||
|
||||
Piece current = tl.initial;
|
||||
|
||||
difference_type elements_done = 0;
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
difference_type total_elements_done = 0;
|
||||
#endif
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Invariant: current must be a valid (maybe empty) range.
|
||||
RandomAccessIterator begin = current.first, end = current.second;
|
||||
difference_type n = end - begin;
|
||||
|
||||
if (n > base_case_n)
|
||||
{
|
||||
// Divide.
|
||||
RandomAccessIterator 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<Comparator, value_type, value_type, bool> pred(comp, *pivot_pos);
|
||||
|
||||
// Divide, leave pivot unchanged in last place.
|
||||
RandomAccessIterator 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);
|
||||
#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 stricly larger than the pivot.
|
||||
__gnu_parallel::unary_negate<__gnu_parallel::binder1st<Comparator, value_type, value_type, bool>, value_type> pred(__gnu_parallel::binder1st<Comparator, value_type, value_type, 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);
|
||||
#endif
|
||||
// Always push larger part onto stack.
|
||||
if (((split_pos1 + 1) - begin) < (end - (split_pos2)))
|
||||
{
|
||||
// Right side larger.
|
||||
if ((split_pos2) != end)
|
||||
tl.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.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;
|
||||
#endif
|
||||
|
||||
// Prefer own stack, small pieces.
|
||||
if (tl.leftover_parts.pop_front(current))
|
||||
continue;
|
||||
|
||||
#pragma omp atomic
|
||||
*tl.elements_leftover -= elements_done;
|
||||
elements_done = 0;
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
double search_start = omp_get_wtime();
|
||||
#endif
|
||||
|
||||
// Look for new work.
|
||||
bool success = false;
|
||||
while (*tl.elements_leftover > 0 && !success
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
// Possible dead-lock.
|
||||
&& (omp_get_wtime() < (search_start + 1.0))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
thread_index_t victim;
|
||||
victim = rng(num_threads);
|
||||
|
||||
// Large pieces.
|
||||
success = (victim != iam) && tls[victim]->leftover_parts.pop_back(current);
|
||||
if (!success)
|
||||
yield();
|
||||
#if !defined(__ICC) && !defined(__ECC)
|
||||
#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));
|
||||
}
|
||||
#endif
|
||||
if (!success)
|
||||
{
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_GLIBCXX_PARALLEL_ASSERT(*tl.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 n Length of the sequence to sort.
|
||||
* @param num_threads Number of threads that are allowed to work on
|
||||
* this part.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
parallel_sort_qsb(RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Comparator comp,
|
||||
typename std::iterator_traits<RandomAccessIterator>::difference_type n, int num_threads)
|
||||
{
|
||||
_GLIBCXX_CALL(end - begin)
|
||||
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef std::pair<RandomAccessIterator, RandomAccessIterator> Piece;
|
||||
|
||||
typedef QSBThreadLocal<RandomAccessIterator> tls_type;
|
||||
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
// At least one element per processor.
|
||||
if (num_threads > n)
|
||||
num_threads = static_cast<thread_index_t>(n);
|
||||
|
||||
tls_type** tls = new tls_type*[num_threads];
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
// Initialize variables per processor.
|
||||
qsb_initialize(tls, num_threads * (thread_index_t)(log2(n) + 1));
|
||||
|
||||
// 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 difference_type elements_leftover = n;
|
||||
for (int i = 0; i < num_threads; i++)
|
||||
{
|
||||
tls[i]->elements_leftover = &elements_leftover;
|
||||
tls[i]->num_threads = num_threads;
|
||||
tls[i]->global = std::make_pair(begin, end);
|
||||
|
||||
// Just in case nothing is left to assign.
|
||||
tls[i]->initial = std::make_pair(end, end);
|
||||
}
|
||||
|
||||
// Initial splitting, recursively.
|
||||
int old_nested = omp_get_nested();
|
||||
omp_set_nested(true);
|
||||
|
||||
// Main recursion call.
|
||||
qsb_conquer(tls, begin, begin + n, comp, 0, num_threads);
|
||||
|
||||
omp_set_nested(old_nested);
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
// All stack must be empty.
|
||||
Piece dummy;
|
||||
for (int i = 1; i < num_threads; i++)
|
||||
_GLIBCXX_PARALLEL_ASSERT(!tls[i]->leftover_parts.pop_back(dummy));
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < num_threads; i++)
|
||||
delete tls[i];
|
||||
delete[] tls;
|
||||
}
|
||||
} // namespace __gnu_parallel
|
||||
|
||||
#endif
|
358
libstdc++-v3/include/parallel/base.h
Normal file
358
libstdc++-v3/include/parallel/base.h
Normal file
@ -0,0 +1,358 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/base.h
|
||||
* @brief Sequential helper functions.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_BASE_H
|
||||
#define _GLIBCXX_PARALLEL_BASE_H 1
|
||||
|
||||
#include <parallel/features.h>
|
||||
#include <functional>
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <parallel/parallel.h>
|
||||
#include <cstdio>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
// XXX remove std::duplicates from here if possible,
|
||||
// XXX but keep minimal dependencies.
|
||||
|
||||
/** @brief Calculates the rounded-down logrithm of @c n for base 2.
|
||||
* @param n Argument.
|
||||
* @return Returns 0 for argument 0.
|
||||
*/
|
||||
template<typename Size>
|
||||
inline Size
|
||||
log2(Size n)
|
||||
{
|
||||
Size k;
|
||||
for (k = 0; n != 1; n >>= 1)
|
||||
++k;
|
||||
return k;
|
||||
}
|
||||
|
||||
/** @brief Encode two integers into one __gnu_parallel::lcas_t.
|
||||
* @param a First integer, to be encoded in the most-significant @c
|
||||
* lcas_t_bits/2 bits.
|
||||
* @param b Second integer, to be encoded in the least-significant
|
||||
* @c lcas_t_bits/2 bits.
|
||||
* @return __gnu_parallel::lcas_t value encoding @c a and @c b.
|
||||
* @see decode2
|
||||
*/
|
||||
inline lcas_t
|
||||
encode2(int a, int b) //must all be non-negative, actually
|
||||
{
|
||||
return (((lcas_t)a) << (lcas_t_bits / 2)) | (((lcas_t)b) << 0);
|
||||
}
|
||||
|
||||
/** @brief Decode two integers from one __gnu_parallel::lcas_t.
|
||||
* @param x __gnu_parallel::lcas_t to decode integers from.
|
||||
* @param a First integer, to be decoded from the most-significant
|
||||
* @c lcas_t_bits/2 bits of @c x.
|
||||
* @param b Second integer, to be encoded in the least-significant
|
||||
* @c lcas_t_bits/2 bits of @c x.
|
||||
* @see encode2
|
||||
*/
|
||||
inline void
|
||||
decode2(lcas_t x, int& a, int& b)
|
||||
{
|
||||
a = (int)((x >> (lcas_t_bits / 2)) & lcas_t_mask);
|
||||
b = (int)((x >> 0 ) & lcas_t_mask);
|
||||
}
|
||||
|
||||
/** @brief Constructs predicate for equality from strict weak
|
||||
* ordering predicate
|
||||
*/
|
||||
// XXX comparator at the end, as per others
|
||||
template<typename Comparator, typename T1, typename T2>
|
||||
class equal_from_less : public std::binary_function<T1, T2, bool>
|
||||
{
|
||||
private:
|
||||
Comparator& comp;
|
||||
|
||||
public:
|
||||
equal_from_less(Comparator& _comp) : comp(_comp) { }
|
||||
|
||||
bool operator()(const T1& a, const T2& b)
|
||||
{
|
||||
// FIXME: wrong in general (T1 != T2)
|
||||
return !comp(a, b) && !comp(b, a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @brief Similar to std::equal_to, but allows two different types. */
|
||||
template<typename T1, typename T2>
|
||||
struct equal_to : std::binary_function<T1, T2, bool>
|
||||
{
|
||||
bool operator()(const T1& t1, const T2& t2) const
|
||||
{ return t1 == t2; }
|
||||
};
|
||||
|
||||
/** @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 first_argument_type, typename second_argument_type, typename result_type>
|
||||
class binder1st
|
||||
: public std::unary_function<second_argument_type, result_type>
|
||||
{
|
||||
protected:
|
||||
_Operation op;
|
||||
first_argument_type value;
|
||||
|
||||
public:
|
||||
binder1st(const _Operation& __x,
|
||||
const first_argument_type& __y)
|
||||
: op(__x), value(__y) { }
|
||||
|
||||
result_type
|
||||
operator()(const second_argument_type& __x)
|
||||
{ return op(value, __x); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 109. Missing binders for non-const sequence elements
|
||||
result_type
|
||||
operator()(second_argument_type& __x) const
|
||||
{ return op(value, __x); }
|
||||
};
|
||||
|
||||
/** @brief Similar to std::binder2nd, but giving the argument types explicitly. */
|
||||
template<typename _Operation, typename first_argument_type, typename second_argument_type, typename result_type>
|
||||
class binder2nd
|
||||
: public std::unary_function<first_argument_type, result_type>
|
||||
{
|
||||
protected:
|
||||
_Operation op;
|
||||
second_argument_type value;
|
||||
|
||||
public:
|
||||
binder2nd(const _Operation& __x,
|
||||
const second_argument_type& __y)
|
||||
: op(__x), value(__y) { }
|
||||
|
||||
result_type
|
||||
operator()(const first_argument_type& __x) const
|
||||
{ return op(__x, value); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 109. Missing binders for non-const sequence elements
|
||||
result_type
|
||||
operator()(first_argument_type& __x)
|
||||
{ return op(__x, value); }
|
||||
};
|
||||
|
||||
/** @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; }
|
||||
};
|
||||
|
||||
|
||||
template<typename T, typename _DifferenceTp>
|
||||
class pseudo_sequence;
|
||||
|
||||
/** @brief Iterator associated with __gnu_parallel::pseudo_sequence.
|
||||
* If features the usual random-access iterator functionality.
|
||||
* @param T Sequence value type.
|
||||
* @param difference_type Sequence difference type.
|
||||
*/
|
||||
template<typename T, typename _DifferenceTp>
|
||||
class pseudo_sequence_iterator
|
||||
{
|
||||
public:
|
||||
typedef _DifferenceTp difference_type;
|
||||
|
||||
private:
|
||||
typedef pseudo_sequence_iterator<T, _DifferenceTp> type;
|
||||
|
||||
const T& val;
|
||||
difference_type pos;
|
||||
|
||||
public:
|
||||
pseudo_sequence_iterator(const T& val, difference_type pos)
|
||||
: val(val), pos(pos) { }
|
||||
|
||||
// Pre-increment operator.
|
||||
type&
|
||||
operator++()
|
||||
{
|
||||
++pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Post-increment operator.
|
||||
const type
|
||||
operator++(int)
|
||||
{ return type(pos++); }
|
||||
|
||||
const T&
|
||||
operator*() const
|
||||
{ return val; }
|
||||
|
||||
const T&
|
||||
operator[](difference_type) const
|
||||
{ return val; }
|
||||
|
||||
bool
|
||||
operator==(const type& i2)
|
||||
{ return pos == i2.pos; }
|
||||
|
||||
difference_type
|
||||
operator!=(const type& i2)
|
||||
{ return pos != i2.pos; }
|
||||
|
||||
difference_type
|
||||
operator-(const type& i2)
|
||||
{ return pos - i2.pos; }
|
||||
};
|
||||
|
||||
/** @brief Sequence that conceptually consists of multiple copies of
|
||||
the same element.
|
||||
* The copies are not stored explicitly, of course.
|
||||
* @param T Sequence value type.
|
||||
* @param difference_type Sequence difference type.
|
||||
*/
|
||||
template<typename T, typename _DifferenceTp>
|
||||
class pseudo_sequence
|
||||
{
|
||||
typedef pseudo_sequence<T, _DifferenceTp> type;
|
||||
|
||||
public:
|
||||
typedef _DifferenceTp difference_type;
|
||||
typedef pseudo_sequence_iterator<T, uint64> iterator; //better case down to uint64, than up to _DifferenceTp
|
||||
|
||||
/** @brief Constructor.
|
||||
* @param val Element of the sequence.
|
||||
* @param count Number of (virtual) copies.
|
||||
*/
|
||||
pseudo_sequence(const T& val, difference_type count)
|
||||
: val(val), count(count) { }
|
||||
|
||||
/** @brief Begin iterator. */
|
||||
iterator
|
||||
begin() const
|
||||
{ return iterator(val, 0); }
|
||||
|
||||
/** @brief End iterator. */
|
||||
iterator
|
||||
end() const
|
||||
{ return iterator(val, count); }
|
||||
|
||||
private:
|
||||
const T& val;
|
||||
difference_type count;
|
||||
};
|
||||
|
||||
/** @brief Functor that does nothing */
|
||||
template<typename _ValueTp>
|
||||
class void_functor
|
||||
{
|
||||
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 RandomAccessIterator, typename Comparator>
|
||||
RandomAccessIterator
|
||||
median_of_three_iterators(RandomAccessIterator a, RandomAccessIterator b,
|
||||
RandomAccessIterator c, Comparator& comp)
|
||||
{
|
||||
if (comp(*a, *b))
|
||||
if (comp(*b, *c))
|
||||
return b;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid the use of assert, because we're trying to keep the <cassert>
|
||||
// include out of the mix. (Same as debug mode).
|
||||
inline void
|
||||
__replacement_assert(const char* __file, int __line,
|
||||
const char* __function, const char* __condition)
|
||||
{
|
||||
std::printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line,
|
||||
__function, __condition);
|
||||
__builtin_abort();
|
||||
}
|
||||
|
||||
#define _GLIBCXX_PARALLEL_ASSERT(_Condition) \
|
||||
do \
|
||||
{ \
|
||||
if (!(_Condition)) \
|
||||
__gnu_parallel::__replacement_assert(__FILE__, __LINE__, \
|
||||
__PRETTY_FUNCTION__, #_Condition); \
|
||||
} while (false)
|
||||
|
||||
} //namespace __gnu_parallel
|
||||
|
||||
#endif
|
||||
|
48
libstdc++-v3/include/parallel/basic_iterator.h
Normal file
48
libstdc++-v3/include/parallel/basic_iterator.h
Normal file
@ -0,0 +1,48 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/basic_iterator.h
|
||||
* @brief Includes the original header files concerned with iterators
|
||||
* except for stream iterators.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_BASIC_ITERATOR_H
|
||||
#define _GLIBCXX_PARALLEL_BASIC_ITERATOR_H 1
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <cstddef>
|
||||
#include <bits/stl_iterator_base_types.h>
|
||||
#include <bits/stl_iterator_base_funcs.h>
|
||||
#include <bits/stl_iterator.h>
|
||||
|
||||
#endif /* _GLIBCXX_BASIC_ITERATOR_H */
|
148
libstdc++-v3/include/parallel/checkers.h
Normal file
148
libstdc++-v3/include/parallel/checkers.h
Normal file
@ -0,0 +1,148 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/checkers.h
|
||||
* @brief Routines for checking the correctness of algorithm results.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_CHECKERS
|
||||
#define _GLIBCXX_PARALLEL_CHECKERS 1
|
||||
|
||||
#include <functional>
|
||||
#include <cstdio>
|
||||
#include <bits/stl_algobase.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
// XXX Comparator default template argument
|
||||
template<typename InputIterator, typename Comparator>
|
||||
bool
|
||||
is_sorted(InputIterator begin, InputIterator end, Comparator comp = std::less<typename std::iterator_traits<InputIterator>::value_type>())
|
||||
{
|
||||
if (begin == end)
|
||||
return true;
|
||||
|
||||
InputIterator current(begin), recent(begin);
|
||||
|
||||
unsigned long long position = 1;
|
||||
for (current++; current != end; current++)
|
||||
{
|
||||
if (comp(*current, *recent))
|
||||
{
|
||||
printf("is_sorted: check failed before position %i.\n", position);
|
||||
return false;
|
||||
}
|
||||
recent = current;
|
||||
position++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether @c [begin, @c end) is sorted according to @c comp.
|
||||
* Prints the position in case an misordered pair is found.
|
||||
* @param begin Begin iterator of sequence.
|
||||
* @param end End iterator of sequence.
|
||||
* @param first_failure The first failure is returned in this variable.
|
||||
* @param comp Comparator.
|
||||
* @return @c true if sorted, @c false otherwise.
|
||||
*/
|
||||
// XXX Comparator default template argument
|
||||
template<typename InputIterator, typename Comparator>
|
||||
bool
|
||||
is_sorted_failure(InputIterator begin, InputIterator end, InputIterator& first_failure, Comparator comp = std::less<typename std::iterator_traits<InputIterator>::value_type>())
|
||||
{
|
||||
if (begin == end)
|
||||
return true;
|
||||
|
||||
InputIterator current(begin), recent(begin);
|
||||
|
||||
unsigned long long position = 1;
|
||||
for (current++; current != end; current++)
|
||||
{
|
||||
if (comp(*current, *recent))
|
||||
{
|
||||
first_failure = current;
|
||||
printf("is_sorted: check failed before position %lld.\n", position);
|
||||
return false;
|
||||
}
|
||||
recent = current;
|
||||
position++;
|
||||
}
|
||||
|
||||
first_failure = end;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether @c [begin, @c end) is sorted according to @c comp.
|
||||
* Prints all misordered pair, including the surrounding two elements.
|
||||
* @param begin Begin iterator of sequence.
|
||||
* @param end End iterator of sequence.
|
||||
* @param comp Comparator.
|
||||
* @return @c true if sorted, @c false otherwise.
|
||||
*/
|
||||
template<typename InputIterator, typename Comparator>
|
||||
bool
|
||||
// XXX Comparator default template argument
|
||||
is_sorted_print_failures(InputIterator begin, InputIterator end, Comparator comp = std::less<typename std::iterator_traits<InputIterator>::value_type>())
|
||||
{
|
||||
if (begin == end)
|
||||
return true;
|
||||
|
||||
InputIterator recent(begin);
|
||||
bool ok = true;
|
||||
|
||||
for (InputIterator pos(begin + 1); pos != end; pos++)
|
||||
{
|
||||
if (comp(*pos, *recent))
|
||||
{
|
||||
printf("%ld: %d %d %d %d\n", pos - begin, *(pos - 2),
|
||||
*(pos- 1), *pos, *(pos + 1));
|
||||
ok = false;
|
||||
}
|
||||
recent = pos;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
338
libstdc++-v3/include/parallel/compatibility.h
Normal file
338
libstdc++-v3/include/parallel/compatibility.h
Normal file
@ -0,0 +1,338 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/compatibility.h
|
||||
* @brief Compatibility layer, mostly concerned with atomic operations.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_COMPATIBILITY_H
|
||||
#define _GLIBCXX_PARALLEL_COMPATIBILITY_H 1
|
||||
|
||||
#include <parallel/types.h>
|
||||
#include <parallel/base.h>
|
||||
|
||||
#if defined(__SUNPRO_CC) && defined(__sparc)
|
||||
#include <sys/atomic.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <Windows.h>
|
||||
#include <intrin.h>
|
||||
#undef max
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
#if defined(__ICC)
|
||||
template<typename must_be_int = int>
|
||||
int32 faa32(int32* x, int32 inc)
|
||||
{
|
||||
asm volatile("lock xadd %0,%1"
|
||||
: "=r" (inc), "=m" (*x)
|
||||
: "0" (inc)
|
||||
: "memory");
|
||||
return inc;
|
||||
}
|
||||
#if defined(__x86_64)
|
||||
template<typename must_be_int = int>
|
||||
int64 faa64(int64* x, int64 inc)
|
||||
{
|
||||
asm volatile("lock xadd %0,%1"
|
||||
: "=r" (inc), "=m" (*x)
|
||||
: "0" (inc)
|
||||
: "memory");
|
||||
return inc;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// atomic functions only work on integers
|
||||
|
||||
/** @brief Add a value to a variable, atomically.
|
||||
*
|
||||
* Implementation is heavily platform-dependent.
|
||||
* @param ptr Pointer to a 32-bit signed integer.
|
||||
* @param addend Value to add.
|
||||
*/
|
||||
inline int32
|
||||
fetch_and_add_32(volatile int32* ptr, int32 addend)
|
||||
{
|
||||
#if defined(__ICC) //x86 version
|
||||
return _InterlockedExchangeAdd((void*)ptr, addend);
|
||||
#elif defined(__ECC) //IA-64 version
|
||||
return _InterlockedExchangeAdd((void*)ptr, addend);
|
||||
#elif defined(__ICL) || defined(_MSC_VER)
|
||||
return _InterlockedExchangeAdd(reinterpret_cast<volatile long*>(ptr), addend);
|
||||
#elif defined(__GNUC__)
|
||||
return __sync_fetch_and_add(ptr, addend);
|
||||
#elif defined(__SUNPRO_CC) && defined(__sparc)
|
||||
volatile int32 before, after;
|
||||
do
|
||||
{
|
||||
before = *ptr;
|
||||
after = before + addend;
|
||||
} while (atomic_cas_32((volatile unsigned int*)ptr, before, after) != before);
|
||||
return before;
|
||||
#else //fallback, slow
|
||||
#pragma message("slow fetch_and_add_32")
|
||||
int32 res;
|
||||
#pragma omp critical
|
||||
{
|
||||
res = *ptr;
|
||||
*(ptr) += addend;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Add a value to a variable, atomically.
|
||||
*
|
||||
* Implementation is heavily platform-dependent.
|
||||
* @param ptr Pointer to a 64-bit signed integer.
|
||||
* @param addend Value to add.
|
||||
*/
|
||||
inline int64
|
||||
fetch_and_add_64(volatile int64* ptr, int64 addend)
|
||||
{
|
||||
#if defined(__ICC) && defined(__x86_64) //x86 version
|
||||
return faa64<int>((int64*)ptr, addend);
|
||||
#elif defined(__ECC) //IA-64 version
|
||||
return _InterlockedExchangeAdd64((void*)ptr, addend);
|
||||
#elif defined(__ICL) || defined(_MSC_VER)
|
||||
#ifndef _WIN64
|
||||
_GLIBCXX_PARALLEL_ASSERT(false); //not available in this case
|
||||
return 0;
|
||||
#else
|
||||
return _InterlockedExchangeAdd64(ptr, addend);
|
||||
#endif
|
||||
#elif defined(__GNUC__) && defined(__x86_64)
|
||||
return __sync_fetch_and_add(ptr, addend);
|
||||
#elif defined(__GNUC__) && defined(__i386) && \
|
||||
(defined(__i686) || defined(__pentium4) || defined(__athlon))
|
||||
return __sync_fetch_and_add(ptr, addend);
|
||||
#elif defined(__SUNPRO_CC) && defined(__sparc)
|
||||
volatile int64 before, after;
|
||||
do
|
||||
{
|
||||
before = *ptr;
|
||||
after = before + addend;
|
||||
} while (atomic_cas_64((volatile unsigned long long*)ptr, before, after) != before);
|
||||
return before;
|
||||
#else //fallback, slow
|
||||
#if defined(__GNUC__) && defined(__i386)
|
||||
// XXX doesn't work with -march=native
|
||||
//#warning "please compile with -march=i686 or better"
|
||||
#endif
|
||||
#pragma message("slow fetch_and_add_64")
|
||||
int64 res;
|
||||
#pragma omp critical
|
||||
{
|
||||
res = *ptr;
|
||||
*(ptr) += addend;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Add a value to a variable, atomically.
|
||||
*
|
||||
* Implementation is heavily platform-dependent.
|
||||
* @param ptr Pointer to a signed integer.
|
||||
* @param addend Value to add.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T
|
||||
fetch_and_add(volatile T* ptr, T addend)
|
||||
{
|
||||
if (sizeof(T) == sizeof(int32))
|
||||
return (T)fetch_and_add_32((volatile int32*) ptr, (int32)addend);
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
return (T)fetch_and_add_64((volatile int64*) ptr, (int64)addend);
|
||||
else
|
||||
_GLIBCXX_PARALLEL_ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__ICC)
|
||||
|
||||
template<typename must_be_int = int>
|
||||
inline int32
|
||||
cas32(volatile int32* ptr, int32 old, int32 nw)
|
||||
{
|
||||
int32 before;
|
||||
__asm__ __volatile__("lock; cmpxchgl %1,%2"
|
||||
: "=a"(before)
|
||||
: "q"(nw), "m"(*(volatile long long*)(ptr)), "0"(old)
|
||||
: "memory");
|
||||
return before;
|
||||
}
|
||||
|
||||
#if defined(__x86_64)
|
||||
template<typename must_be_int = int>
|
||||
inline int64
|
||||
cas64(volatile int64 *ptr, int64 old, int64 nw)
|
||||
{
|
||||
int64 before;
|
||||
__asm__ __volatile__("lock; cmpxchgq %1,%2"
|
||||
: "=a"(before)
|
||||
: "q"(nw), "m"(*(volatile long long*)(ptr)), "0"(old)
|
||||
: "memory");
|
||||
return before;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @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.
|
||||
* @param comparand Compare value.
|
||||
* @param replacement Replacement value.
|
||||
*/
|
||||
inline bool
|
||||
compare_and_swap_32(volatile int32* ptr, int32 comparand, int32 replacement)
|
||||
{
|
||||
#if defined(__ICC) //x86 version
|
||||
return _InterlockedCompareExchange((void*)ptr, replacement, comparand) == comparand;
|
||||
#elif defined(__ECC) //IA-64 version
|
||||
return _InterlockedCompareExchange((void*)ptr, replacement, comparand) == comparand;
|
||||
#elif defined(__ICL) || defined(_MSC_VER)
|
||||
return _InterlockedCompareExchange(reinterpret_cast<volatile long*>(ptr), replacement, comparand) == comparand;
|
||||
#elif defined(__GNUC__)
|
||||
return __sync_bool_compare_and_swap(ptr, comparand, replacement);
|
||||
#elif defined(__SUNPRO_CC) && defined(__sparc)
|
||||
return atomic_cas_32((volatile unsigned int*)ptr, comparand, replacement) == comparand;
|
||||
#else
|
||||
#pragma message("slow compare_and_swap_32")
|
||||
bool res = false;
|
||||
#pragma omp critical
|
||||
{
|
||||
if (*ptr == comparand)
|
||||
{
|
||||
*ptr = replacement;
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @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.
|
||||
* @param comparand Compare value.
|
||||
* @param replacement Replacement value.
|
||||
*/
|
||||
inline bool
|
||||
compare_and_swap_64(volatile int64* ptr, int64 comparand, int64 replacement)
|
||||
{
|
||||
#if defined(__ICC) && defined(__x86_64) //x86 version
|
||||
return cas64<int>(ptr, comparand, replacement) == comparand;
|
||||
#elif defined(__ECC) //IA-64 version
|
||||
return _InterlockedCompareExchange64((void*)ptr, replacement, comparand) == comparand;
|
||||
#elif defined(__ICL) || defined(_MSC_VER)
|
||||
#ifndef _WIN64
|
||||
_GLIBCXX_PARALLEL_ASSERT(false); //not available in this case
|
||||
return 0;
|
||||
#else
|
||||
return _InterlockedCompareExchange64(ptr, replacement, comparand) == comparand;
|
||||
#endif
|
||||
|
||||
#elif defined(__GNUC__) && defined(__x86_64)
|
||||
return __sync_bool_compare_and_swap(ptr, comparand, replacement);
|
||||
#elif defined(__GNUC__) && defined(__i386) && \
|
||||
(defined(__i686) || defined(__pentium4) || defined(__athlon))
|
||||
return __sync_bool_compare_and_swap(ptr, comparand, replacement);
|
||||
#elif defined(__SUNPRO_CC) && defined(__sparc)
|
||||
return atomic_cas_64((volatile unsigned long long*)ptr, comparand, replacement) == comparand;
|
||||
#else
|
||||
#if defined(__GNUC__) && defined(__i386)
|
||||
// XXX -march=native
|
||||
//#warning "please compile with -march=i686 or better"
|
||||
#endif
|
||||
#pragma message("slow compare_and_swap_64")
|
||||
bool res = false;
|
||||
#pragma omp critical
|
||||
{
|
||||
if (*ptr == comparand)
|
||||
{
|
||||
*ptr = replacement;
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @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.
|
||||
* @param comparand Compare value.
|
||||
* @param replacement Replacement value. */
|
||||
template<typename T>
|
||||
inline bool
|
||||
compare_and_swap(volatile T* ptr, T comparand, T replacement)
|
||||
{
|
||||
if (sizeof(T) == sizeof(int32))
|
||||
return compare_and_swap_32((volatile int32*) ptr, (int32)comparand, (int32)replacement);
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
return compare_and_swap_64((volatile int64*) ptr, (int64)comparand, (int64)replacement);
|
||||
else
|
||||
_GLIBCXX_PARALLEL_ASSERT(false);
|
||||
}
|
||||
|
||||
/** @brief Yield the control to another thread, without waiting for
|
||||
the end to the time slice. */
|
||||
inline void
|
||||
yield()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Sleep(0);
|
||||
#else
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
#endif
|
76
libstdc++-v3/include/parallel/compiletime_settings.h
Normal file
76
libstdc++-v3/include/parallel/compiletime_settings.h
Normal file
@ -0,0 +1,76 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/compiletime_settings.h
|
||||
* @brief Defines on options concerning debugging and performance, at
|
||||
* compile-time.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
/** @brief Determine verbosity level of the parallel mode.
|
||||
* Level 1 prints a message each time when entering a parallel-mode function. */
|
||||
#define _GLIBCXX_VERBOSE_LEVEL 0
|
||||
|
||||
/** @def _GLIBCXX_CALL
|
||||
* @brief Macro to produce log message when entering a function.
|
||||
* @param n Input size.
|
||||
* @see _GLIBCXX_VERBOSE_LEVEL */
|
||||
#if (_GLIBCXX_VERBOSE_LEVEL == 0)
|
||||
#define _GLIBCXX_CALL(n)
|
||||
#endif
|
||||
#if (_GLIBCXX_VERBOSE_LEVEL == 1)
|
||||
#define _GLIBCXX_CALL(n) printf(" %s:\niam = %d, n = %ld, num_threads = %d\n", __PRETTY_FUNCTION__, omp_get_thread_num(), (n), get_max_threads());
|
||||
#endif
|
||||
|
||||
/** @brief Use floating-point scaling instead of modulo for mapping
|
||||
* random numbers to a range. This can be faster on certain CPUs. */
|
||||
#define _GLIBCXX_SCALE_DOWN_FPU 0
|
||||
|
||||
/** @brief Switch on many _GLIBCXX_PARALLEL_ASSERTions in parallel code.
|
||||
* Should be switched on only locally. */
|
||||
#define _GLIBCXX_ASSERTIONS 0
|
||||
|
||||
/** @brief Switch on many _GLIBCXX_PARALLEL_ASSERTions in parallel code.
|
||||
* Consider the size of the L1 cache for __gnu_parallel::parallel_random_shuffle(). */
|
||||
#define _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1 0
|
||||
/** @brief Switch on many _GLIBCXX_PARALLEL_ASSERTions in parallel code.
|
||||
* Consider the size of the TLB for __gnu_parallel::parallel_random_shuffle(). */
|
||||
#define _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB 0
|
||||
|
||||
/** @brief First copy the data, sort it locally, and merge it back
|
||||
* (0); or copy it back after everyting is done (1).
|
||||
*
|
||||
* Recommendation: 0 */
|
||||
#define _GLIBCXX_MULTIWAY_MERGESORT_COPY_LAST 0
|
||||
|
68
libstdc++-v3/include/parallel/equally_split.h
Normal file
68
libstdc++-v3/include/parallel/equally_split.h
Normal file
@ -0,0 +1,68 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/equally_split.h
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_EQUALLY_SPLIT_H
|
||||
#define _GLIBCXX_PARALLEL_EQUALLY_SPLIT_H 1
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @brief Function to split a sequence into parts of almost equal size.
|
||||
*
|
||||
* The resulting sequence s of length p+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 p Number of parts
|
||||
* @param s Splitters
|
||||
* @returns End of splitter sequence, i. e. @c s+p+1 */
|
||||
template<typename _DifferenceTp, typename OutputIterator>
|
||||
OutputIterator
|
||||
equally_split(_DifferenceTp n, thread_index_t p, OutputIterator s)
|
||||
{
|
||||
typedef _DifferenceTp difference_type;
|
||||
difference_type chunk_length = n / p, split = n % p, start = 0;
|
||||
for (int i = 0; i < p; i++)
|
||||
{
|
||||
*s++ = start;
|
||||
start += (difference_type(i) < split) ? (chunk_length + 1) : chunk_length;
|
||||
}
|
||||
*s++ = n;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
170
libstdc++-v3/include/parallel/features.h
Normal file
170
libstdc++-v3/include/parallel/features.h
Normal file
@ -0,0 +1,170 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/features.h
|
||||
* @brief Defines on whether to include algorithm variants.
|
||||
*
|
||||
* Less variants reduce executable size and compile time.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_FEATURES_H
|
||||
#define _GLIBCXX_PARALLEL_FEATURES_H 1
|
||||
|
||||
#ifndef _GLIBCXX_MERGESORT
|
||||
/** @def _GLIBCXX_MERGESORT
|
||||
* @brief Include parallel multi-way mergesort.
|
||||
* @see __gnu_parallel::Settings::sort_algorithm */
|
||||
#define _GLIBCXX_MERGESORT 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_QUICKSORT
|
||||
/** @def _GLIBCXX_QUICKSORT
|
||||
* @brief Include parallel unbalanced quicksort.
|
||||
* @see __gnu_parallel::Settings::sort_algorithm */
|
||||
#define _GLIBCXX_QUICKSORT 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_BAL_QUICKSORT
|
||||
/** @def _GLIBCXX_BAL_QUICKSORT
|
||||
* @brief Include parallel dynamically load-balanced quicksort.
|
||||
* @see __gnu_parallel::Settings::sort_algorithm */
|
||||
#define _GLIBCXX_BAL_QUICKSORT 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE
|
||||
/** @def _GLIBCXX_LOSER_TREE
|
||||
* @brief Include guarded (sequences may run empty) loser tree,
|
||||
* moving objects.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE_EXPLICIT
|
||||
/** @def _GLIBCXX_LOSER_TREE_EXPLICIT
|
||||
* @brief Include standard loser tree, storing two flags for infimum
|
||||
* and supremum.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE_EXPLICIT 0
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE_REFERENCE
|
||||
/** @def _GLIBCXX_LOSER_TREE_REFERENCE
|
||||
* @brief Include some loser tree variant.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE_REFERENCE 0
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE_POINTER
|
||||
/** @def _GLIBCXX_LOSER_TREE_POINTER
|
||||
* @brief Include some loser tree variant.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE_POINTER 0
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE_UNGUARDED
|
||||
/** @def _GLIBCXX_LOSER_TREE_UNGUARDED
|
||||
* @brief Include unguarded (sequences must not run empty) loser
|
||||
* tree, moving objects.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE_UNGUARDED 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
|
||||
/** @def _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED
|
||||
* @brief Include some loser tree variant.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE_POINTER_UNGUARDED 0
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE_COMBINED
|
||||
/** @def _GLIBCXX_LOSER_TREE_COMBINED
|
||||
* @brief Include some loser tree variant.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE_COMBINED 0
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_LOSER_TREE_SENTINEL
|
||||
/** @def _GLIBCXX_LOSER_TREE_SENTINEL
|
||||
* @brief Include some loser tree variant.
|
||||
* @see __gnu_parallel::Settings multiway_merge_algorithm */
|
||||
#define _GLIBCXX_LOSER_TREE_SENTINEL 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _GLIBCXX_FIND_GROWING_BLOCKS
|
||||
/** @brief Include the growing blocks variant for std::find.
|
||||
* @see __gnu_parallel::Settings::find_distribution */
|
||||
#define _GLIBCXX_FIND_GROWING_BLOCKS 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_FIND_CONSTANT_SIZE_BLOCKS
|
||||
/** @brief Include the equal-sized blocks variant for std::find.
|
||||
* @see __gnu_parallel::Settings::find_distribution */
|
||||
#define _GLIBCXX_FIND_CONSTANT_SIZE_BLOCKS 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_FIND_EQUAL_SPLIT
|
||||
/** @def _GLIBCXX_FIND_EQUAL_SPLIT
|
||||
* @brief Include the equal splitting variant for std::find.
|
||||
* @see __gnu_parallel::Settings::find_distribution */
|
||||
#define _GLIBCXX_FIND_EQUAL_SPLIT 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _GLIBCXX_TREE_INITIAL_SPLITTING
|
||||
/** @def _GLIBCXX_TREE_INITIAL_SPLITTING
|
||||
* @brief Include the initial splitting variant for
|
||||
* _Rb_tree::insert_unique(InputIterator beg, InputIterator end).
|
||||
* @see __gnu_parallel::_Rb_tree */
|
||||
#define _GLIBCXX_TREE_INITIAL_SPLITTING 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_TREE_DYNAMIC_BALANCING
|
||||
/** @def _GLIBCXX_TREE_DYNAMIC_BALANCING
|
||||
* @brief Include the dynamic balancing variant for
|
||||
* _Rb_tree::insert_unique(InputIterator beg, InputIterator end).
|
||||
* @see __gnu_parallel::_Rb_tree */
|
||||
#define _GLIBCXX_TREE_DYNAMIC_BALANCING 1
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_TREE_FULL_COPY
|
||||
/** @def _GLIBCXX_TREE_FULL_COPY
|
||||
* @brief In order to sort the input sequence of
|
||||
* _Rb_tree::insert_unique(InputIterator beg, InputIterator end) a
|
||||
* full copy of the input elements is done.
|
||||
* @see __gnu_parallel::_Rb_tree */
|
||||
#define _GLIBCXX_TREE_FULL_COPY 1
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
340
libstdc++-v3/include/parallel/find.h
Normal file
340
libstdc++-v3/include/parallel/find.h
Normal file
@ -0,0 +1,340 @@
|
||||
/// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/find.h
|
||||
* @brief Parallel implementation base for std::find(), std::equal()
|
||||
* and related functions.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze and Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_FIND_H
|
||||
#define _GLIBCXX_PARALLEL_FIND_H 1
|
||||
|
||||
#include <bits/stl_algobase.h>
|
||||
|
||||
#include <parallel/features.h>
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/compatibility.h>
|
||||
#include <parallel/equally_split.h>
|
||||
|
||||
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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
|
||||
RandomAccessIterator2 begin2, Pred pred, Selector selector)
|
||||
{
|
||||
switch (Settings::find_distribution)
|
||||
{
|
||||
case Settings::GROWING_BLOCKS:
|
||||
return find_template(begin1, end1, begin2, pred, selector, growing_blocks_tag());
|
||||
case Settings::CONSTANT_SIZE_BLOCKS:
|
||||
return find_template(begin1, end1, begin2, pred, selector, constant_size_blocks_tag());
|
||||
case Settings::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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, Pred pred, Selector selector, equal_split_tag)
|
||||
{
|
||||
_GLIBCXX_CALL(end1 - begin1)
|
||||
|
||||
typedef std::iterator_traits<RandomAccessIterator1> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
|
||||
difference_type length = end1 - begin1;
|
||||
|
||||
difference_type result = length;
|
||||
|
||||
const thread_index_t num_threads = get_max_threads();
|
||||
|
||||
// XXX VLA error.
|
||||
difference_type borders[num_threads + 1];
|
||||
equally_split(length, num_threads, borders);
|
||||
|
||||
#pragma omp parallel shared(result) num_threads(num_threads)
|
||||
{
|
||||
int iam = omp_get_thread_num();
|
||||
difference_type pos = borders[iam], limit = borders[iam + 1];
|
||||
|
||||
RandomAccessIterator1 i1 = begin1 + pos;
|
||||
RandomAccessIterator2 i2 = begin2 + pos;
|
||||
for (; pos < limit; pos++)
|
||||
{
|
||||
#pragma omp flush(result)
|
||||
// Result has been set to something lower.
|
||||
if (result < pos)
|
||||
break;
|
||||
|
||||
if (selector(i1, i2, pred))
|
||||
{
|
||||
#pragma omp critical (result)
|
||||
if (result > pos)
|
||||
result = pos;
|
||||
break;
|
||||
}
|
||||
i1++;
|
||||
i2++;
|
||||
}
|
||||
}
|
||||
return std::pair<RandomAccessIterator1, RandomAccessIterator2>(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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
|
||||
RandomAccessIterator2 begin2, Pred pred, Selector selector,
|
||||
growing_blocks_tag)
|
||||
{
|
||||
_GLIBCXX_CALL(end1 - begin1)
|
||||
|
||||
typedef std::iterator_traits<RandomAccessIterator1> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
|
||||
difference_type length = end1 - begin1;
|
||||
|
||||
difference_type sequential_search_size = std::min<difference_type>(length, Settings::find_sequential_search_size);
|
||||
|
||||
// Try it sequentially first.
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2> find_seq_result =
|
||||
selector.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).
|
||||
difference_type next_block_pos = sequential_search_size;
|
||||
difference_type result = length;
|
||||
const thread_index_t num_threads = get_max_threads();
|
||||
|
||||
#pragma omp parallel shared(result) num_threads(num_threads)
|
||||
{
|
||||
// Not within first k elements -> start parallel.
|
||||
thread_index_t iam = omp_get_thread_num();
|
||||
|
||||
difference_type block_size = Settings::find_initial_block_size;
|
||||
difference_type start = fetch_and_add<difference_type>(&next_block_pos, block_size);
|
||||
|
||||
// Get new block, update pointer to next block.
|
||||
difference_type stop = std::min<difference_type>(length, start + block_size);
|
||||
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2> local_result;
|
||||
|
||||
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.sequential_algorithm(begin1 + start, begin1 + stop, begin2 + start, pred);
|
||||
if (local_result.first != (begin1 + stop))
|
||||
{
|
||||
#pragma omp critical(result)
|
||||
if ((local_result.first - begin1) < result)
|
||||
{
|
||||
result = local_result.first - begin1;
|
||||
|
||||
// Result cannot be in future blocks, stop algorithm.
|
||||
fetch_and_add<difference_type>(&next_block_pos, length);
|
||||
}
|
||||
}
|
||||
|
||||
block_size = std::min<difference_type>(block_size * Settings::find_increasing_factor, Settings::find_maximum_block_size);
|
||||
|
||||
// Get new block, update pointer to next block.
|
||||
start = fetch_and_add<difference_type>(&next_block_pos, block_size);
|
||||
stop = (length < (start + block_size)) ? length : (start + block_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Return iterator on found element.
|
||||
return std::pair<RandomAccessIterator1, RandomAccessIterator2>(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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred, typename Selector>
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
find_template(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
|
||||
RandomAccessIterator2 begin2, Pred pred, Selector selector,
|
||||
constant_size_blocks_tag)
|
||||
{
|
||||
_GLIBCXX_CALL(end1 - begin1)
|
||||
typedef std::iterator_traits<RandomAccessIterator1> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
|
||||
difference_type length = end1 - begin1;
|
||||
|
||||
difference_type sequential_search_size = std::min<difference_type>(length, Settings::find_sequential_search_size);
|
||||
|
||||
// Try it sequentially first.
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2> find_seq_result =
|
||||
selector.sequential_algorithm(begin1, begin1 + sequential_search_size, begin2, pred);
|
||||
|
||||
if (find_seq_result.first != (begin1 + sequential_search_size))
|
||||
return find_seq_result;
|
||||
|
||||
difference_type result = length;
|
||||
const thread_index_t num_threads = get_max_threads();
|
||||
|
||||
// Not within first sequential_search_size elements -> start parallel.
|
||||
#pragma omp parallel shared(result) num_threads(num_threads)
|
||||
{
|
||||
thread_index_t iam = omp_get_thread_num();
|
||||
difference_type block_size = Settings::find_initial_block_size;
|
||||
|
||||
difference_type start, stop;
|
||||
|
||||
// First element of thread's current iteration.
|
||||
difference_type iteration_start = sequential_search_size;
|
||||
|
||||
// Where to work (initialization).
|
||||
start = iteration_start + iam * block_size;
|
||||
stop = std::min<difference_type>(length, start + block_size);
|
||||
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator2> local_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.sequential_algorithm(begin1 + start, begin1 + stop, begin2 + start, pred);
|
||||
if (local_result.first != (begin1 + stop))
|
||||
{
|
||||
#pragma omp critical(result)
|
||||
if ((local_result.first - begin1) < result)
|
||||
result = local_result.first - begin1;
|
||||
|
||||
// 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<difference_type>(length, start + block_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Return iterator on found element.
|
||||
return std::pair<RandomAccessIterator1, RandomAccessIterator2>(begin1 + result, begin2 + result);
|
||||
}
|
||||
#endif
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
184
libstdc++-v3/include/parallel/find_selectors.h
Normal file
184
libstdc++-v3/include/parallel/find_selectors.h
Normal file
@ -0,0 +1,184 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/find_selectors.h
|
||||
* @brief Function objects representing different tasks to be plugged
|
||||
* into the parallel find algorithm.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_FIND_FUNCTIONS_H
|
||||
#define _GLIBCXX_PARALLEL_FIND_FUNCTIONS_H 1
|
||||
|
||||
#include <parallel/tags.h>
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <bits/stl_pair.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @brief Base class of all __gnu_parallel::find_template selectors. */
|
||||
struct generic_find_selector
|
||||
{ };
|
||||
|
||||
/**
|
||||
* @brief Test predicate on a single element, used for std::find()
|
||||
* and std::find_if ().
|
||||
*/
|
||||
struct find_if_selector : public generic_find_selector
|
||||
{
|
||||
/** @brief Test on one position.
|
||||
* @param i1 Iterator on first sequence.
|
||||
* @param i2 Iterator on second sequence (unused).
|
||||
* @param pred Find predicate.
|
||||
*/
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline bool
|
||||
operator()(RandomAccessIterator1 i1, RandomAccessIterator2 i2, Pred pred)
|
||||
{ return pred(*i1); }
|
||||
|
||||
/** @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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
sequential_algorithm(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, Pred pred)
|
||||
{
|
||||
return std::make_pair(find_if(begin1, end1, pred, sequential_tag()), begin2);
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Test predicate on two adjacent elements. */
|
||||
struct adjacent_find_selector : public generic_find_selector
|
||||
{
|
||||
/** @brief Test on one position.
|
||||
* @param i1 Iterator on first sequence.
|
||||
* @param i2 Iterator on second sequence (unused).
|
||||
* @param pred Find predicate.
|
||||
*/
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline bool
|
||||
operator()(RandomAccessIterator1 i1, RandomAccessIterator2 i2, Pred pred)
|
||||
{
|
||||
// Passed end iterator is one short.
|
||||
return pred(*i1, *(i1 + 1));
|
||||
}
|
||||
|
||||
/** @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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
sequential_algorithm(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, Pred pred)
|
||||
{
|
||||
// Passed end iterator is one short.
|
||||
RandomAccessIterator1 spot = adjacent_find(begin1, end1 + 1, pred, sequential_tag());
|
||||
if (spot == (end1 + 1))
|
||||
spot = end1;
|
||||
return std::make_pair(spot, begin2);
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Test inverted predicate on a single element. */
|
||||
struct mismatch_selector : public generic_find_selector
|
||||
{
|
||||
/**
|
||||
* @brief Test on one position.
|
||||
* @param i1 Iterator on first sequence.
|
||||
* @param i2 Iterator on second sequence (unused).
|
||||
* @param pred Find predicate.
|
||||
*/
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline bool
|
||||
operator()(RandomAccessIterator1 i1, RandomAccessIterator2 i2, Pred pred)
|
||||
{ return !pred(*i1, *i2); }
|
||||
|
||||
/**
|
||||
* @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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
sequential_algorithm(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, Pred pred)
|
||||
{
|
||||
return mismatch(begin1, end1, begin2, pred, sequential_tag());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @brief Test predicate on several elements. */
|
||||
template<typename ForwardIterator>
|
||||
struct find_first_of_selector : public generic_find_selector
|
||||
{
|
||||
ForwardIterator begin;
|
||||
ForwardIterator end;
|
||||
|
||||
explicit find_first_of_selector(ForwardIterator begin, ForwardIterator end)
|
||||
: begin(begin), 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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline bool
|
||||
operator()(RandomAccessIterator1 i1, RandomAccessIterator2 i2, Pred pred)
|
||||
{
|
||||
for (ForwardIterator pos_in_candidates = begin; pos_in_candidates != 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 RandomAccessIterator1, typename RandomAccessIterator2, typename Pred>
|
||||
inline std::pair<RandomAccessIterator1, RandomAccessIterator2>
|
||||
sequential_algorithm(RandomAccessIterator1 begin1, RandomAccessIterator1 end1, RandomAccessIterator2 begin2, Pred pred)
|
||||
{
|
||||
return std::make_pair(find_first_of(begin1, end1, begin, end, pred, sequential_tag()), begin2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
83
libstdc++-v3/include/parallel/for_each.h
Normal file
83
libstdc++-v3/include/parallel/for_each.h
Normal file
@ -0,0 +1,83 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/for_each.h
|
||||
* @brief Main interface for embarassingly parallel functions.
|
||||
*
|
||||
* The explicit implementation are in other header files, like
|
||||
* workstealing.h, par_loop.h, omp_loop.h, and omp_loop_static.h.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_FOR_EACH_H
|
||||
#define _GLIBCXX_PARALLEL_FOR_EACH_H 1
|
||||
|
||||
#include <parallel/settings.h>
|
||||
#include <parallel/par_loop.h>
|
||||
#include <parallel/omp_loop.h>
|
||||
#include <parallel/workstealing.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @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,
|
||||
* associative operator,...)
|
||||
* @param functionality functor to "process" an element with
|
||||
* user_op (depends on desired functionality, e. g. accumulate,
|
||||
* for_each,...
|
||||
* @param reduction Reduction functor.
|
||||
* @param reduction_start Initial value for reduction.
|
||||
* @param output Output iterator.
|
||||
* @param bound Maximum number of elements processed.
|
||||
* @param parallelism_tag Parallelization method */
|
||||
template<typename InputIterator, typename UserOp, typename Functionality, typename Red, typename Result>
|
||||
UserOp
|
||||
for_each_template_random_access(InputIterator begin, InputIterator end,
|
||||
UserOp user_op, Functionality& functionality,
|
||||
Red reduction, Result reduction_start,
|
||||
Result& output,
|
||||
typename std::iterator_traits<InputIterator>::difference_type bound, 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);
|
||||
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);
|
||||
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);
|
||||
else //e. g. parallel_balanced
|
||||
return for_each_template_random_access_workstealing(begin, end, user_op, functionality, reduction, reduction_start, output, bound);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
343
libstdc++-v3/include/parallel/for_each_selectors.h
Normal file
343
libstdc++-v3/include/parallel/for_each_selectors.h
Normal file
@ -0,0 +1,343 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/for_each_selectors.h
|
||||
* @brief Functors representing different tasks to be plugged into the
|
||||
* generic parallelization methods for embarrassingly parallel functions.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_FOR_EACH_SELECTORS_H
|
||||
#define _GLIBCXX_PARALLEL_FOR_EACH_SELECTORS_H 1
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
|
||||
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 finish_iterator;
|
||||
};
|
||||
|
||||
|
||||
/** @brief std::for_each() selector. */
|
||||
template<typename It>
|
||||
struct for_each_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator.
|
||||
* @param i Iterator referencing object. */
|
||||
template<typename Op>
|
||||
inline bool operator()(Op& o, It i)
|
||||
{
|
||||
o(*i);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief std::generate() selector. */
|
||||
template<typename It>
|
||||
struct generate_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator.
|
||||
* @param i Iterator referencing object. */
|
||||
template<typename Op>
|
||||
inline bool operator()(Op& o, It i)
|
||||
{
|
||||
*i = o();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief std::fill() selector. */
|
||||
template<typename It>
|
||||
struct fill_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param v Current value.
|
||||
* @param i Iterator referencing object. */
|
||||
template<typename Val>
|
||||
inline bool operator()(Val& v, It i)
|
||||
{
|
||||
*i = v;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief std::transform() selector, one input sequence variant. */
|
||||
template<typename It>
|
||||
struct transform1_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator.
|
||||
* @param i Iterator referencing object. */
|
||||
template<typename Op>
|
||||
inline bool operator()(Op& o, It i)
|
||||
{
|
||||
*i.second = o(*i.first);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief std::transform() selector, two input sequences variant. */
|
||||
template<typename It>
|
||||
struct transform2_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator.
|
||||
* @param i Iterator referencing object. */
|
||||
template<typename Op>
|
||||
inline bool operator()(Op& o, It i)
|
||||
{
|
||||
*i.third = o(*i.first, *i.second);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief std::replace() selector. */
|
||||
template<typename It, typename T>
|
||||
struct replace_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Value to replace with. */
|
||||
const T& new_val;
|
||||
|
||||
/** @brief Constructor
|
||||
* @param new_val Value to replace with. */
|
||||
explicit replace_selector(const T &new_val) : new_val(new_val) {}
|
||||
|
||||
/** @brief Functor execution.
|
||||
* @param v Current value.
|
||||
* @param i Iterator referencing object. */
|
||||
inline bool operator()(T& v, It i)
|
||||
{
|
||||
if (*i == v)
|
||||
*i = new_val;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief std::replace() selector. */
|
||||
template<typename It, typename Op, typename T>
|
||||
struct replace_if_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Value to replace with. */
|
||||
const T& new_val;
|
||||
|
||||
/** @brief Constructor.
|
||||
* @param new_val Value to replace with. */
|
||||
explicit replace_if_selector(const T &new_val) : new_val(new_val) { }
|
||||
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator.
|
||||
* @param i Iterator referencing object. */
|
||||
inline bool operator()(Op& o, It i)
|
||||
{
|
||||
if (o(*i))
|
||||
*i = new_val;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief std::count() selector. */
|
||||
template<typename It, typename Diff>
|
||||
struct count_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param v Current value.
|
||||
* @param i Iterator referencing object.
|
||||
* @return 1 if count, 0 if does not count. */
|
||||
template<typename Val>
|
||||
inline Diff operator()(Val& v, It i)
|
||||
{ return (v == *i) ? 1 : 0; }
|
||||
};
|
||||
|
||||
/** @brief std::count_if () selector. */
|
||||
template<typename It, typename Diff>
|
||||
struct count_if_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator.
|
||||
* @param i Iterator referencing object.
|
||||
* @return 1 if count, 0 if does not count. */
|
||||
template<typename Op>
|
||||
inline Diff operator()(Op& o, It i)
|
||||
{ return (o(*i)) ? 1 : 0; }
|
||||
};
|
||||
|
||||
/** @brief std::accumulate() selector. */
|
||||
template<typename It>
|
||||
struct accumulate_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator (unused).
|
||||
* @param i Iterator referencing object.
|
||||
* @return The current value. */
|
||||
template<typename Op>
|
||||
inline typename std::iterator_traits<It>::value_type operator()(Op o, It i)
|
||||
{ return *i; }
|
||||
};
|
||||
|
||||
/** @brief std::inner_product() selector. */
|
||||
template<typename It, typename It2, typename T>
|
||||
struct inner_product_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Begin iterator of first sequence. */
|
||||
It begin1_iterator;
|
||||
|
||||
/** @brief Begin iterator of second sequence. */
|
||||
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) { }
|
||||
|
||||
/** @brief Functor execution.
|
||||
* @param mult Multiplication functor.
|
||||
* @param current Iterator referencing object.
|
||||
* @return Inner product elemental result. */
|
||||
template<typename Op>
|
||||
inline T operator()(Op mult, It current)
|
||||
{
|
||||
typename std::iterator_traits<It>::difference_type position = current - begin1_iterator;
|
||||
return mult(*current, *(begin2_iterator + position));
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Selector that just returns the passed iterator. */
|
||||
template<typename It>
|
||||
struct identity_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param o Operator (unused).
|
||||
* @param i Iterator referencing object.
|
||||
* @return Passed iterator. */
|
||||
template<typename Op>
|
||||
inline It operator()(Op o, It i)
|
||||
{ return i; }
|
||||
};
|
||||
|
||||
/** @brief Selector that returns the difference between two adjacent
|
||||
* elements.
|
||||
*/
|
||||
template<typename It>
|
||||
struct adjacent_difference_selector : public generic_for_each_selector<It>
|
||||
{
|
||||
template<typename Op>
|
||||
inline bool operator()(Op& o, It i)
|
||||
{
|
||||
typename It::first_type go_back_one = i.first;
|
||||
--go_back_one;
|
||||
*i.second = o(*i.first, *go_back_one);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// XXX move into type_traits?
|
||||
/** @brief Functor doing nothing
|
||||
*
|
||||
* For some reduction tasks (this is not a function object, but is
|
||||
* passed as selector dummy parameter.
|
||||
*/
|
||||
struct nothing
|
||||
{
|
||||
/** @brief Functor execution.
|
||||
* @param i Iterator referencing object. */
|
||||
template<typename It>
|
||||
inline void operator()(It i)
|
||||
{ }
|
||||
};
|
||||
|
||||
/** @brief Reduction function doing nothing. */
|
||||
struct dummy_reduct
|
||||
{
|
||||
inline bool operator()(bool /*x*/, bool /*y*/) const
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
/** @brief Reduction for finding the maximum element, using a comparator. */
|
||||
template<typename Comp, typename It>
|
||||
struct min_element_reduct
|
||||
{
|
||||
Comp& comp;
|
||||
|
||||
explicit min_element_reduct(Comp &c) : comp(c)
|
||||
{ }
|
||||
|
||||
inline It operator()(It x, It y)
|
||||
{
|
||||
if (comp(*x, *y))
|
||||
return x;
|
||||
else
|
||||
return y;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Reduction for finding the maximum element, using a comparator. */
|
||||
template<typename Comp, typename It>
|
||||
struct max_element_reduct
|
||||
{
|
||||
Comp& comp;
|
||||
|
||||
explicit max_element_reduct(Comp& c) : comp(c)
|
||||
{ }
|
||||
|
||||
inline It operator()(It x, It y)
|
||||
{
|
||||
if (comp(*x, *y))
|
||||
return y;
|
||||
else
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief General reduction, using a binary operator. */
|
||||
template<typename BinOp>
|
||||
struct accumulate_binop_reduct
|
||||
{
|
||||
BinOp& binop;
|
||||
|
||||
explicit accumulate_binop_reduct(BinOp& b) : binop(b) {}
|
||||
|
||||
template<typename T>
|
||||
inline T operator()(T x, T y) { return binop(x, y); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
203
libstdc++-v3/include/parallel/iterator.h
Normal file
203
libstdc++-v3/include/parallel/iterator.h
Normal file
@ -0,0 +1,203 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/iterator.h
|
||||
* @brief Helper iterator classes for the std::transform() functions.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_ITERATOR_H
|
||||
#define _GLIBCXX_PARALLEL_ITERATOR_H 1
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <bits/stl_pair.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @brief A pair of iterators. The usual iterator operations are
|
||||
* applied to both child iterators.
|
||||
*/
|
||||
template<typename Iterator1, typename Iterator2, typename IteratorCategory>
|
||||
class iterator_pair : public std::pair<Iterator1, Iterator2>
|
||||
{
|
||||
private:
|
||||
typedef iterator_pair<Iterator1, Iterator2, IteratorCategory> type;
|
||||
typedef std::pair<Iterator1, Iterator2> base_type;
|
||||
|
||||
public:
|
||||
typedef IteratorCategory iterator_category;
|
||||
typedef void value_type;
|
||||
|
||||
typedef std::iterator_traits<Iterator1> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef type* pointer;
|
||||
typedef type& reference;
|
||||
|
||||
iterator_pair() { }
|
||||
|
||||
iterator_pair(const Iterator1& first, const Iterator2& second)
|
||||
: base_type(first, second) { }
|
||||
|
||||
// Pre-increment operator.
|
||||
type&
|
||||
operator++()
|
||||
{
|
||||
++base_type::first;
|
||||
++base_type::second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Post-increment operator.
|
||||
const type
|
||||
operator++(int)
|
||||
{ return type(base_type::first++, base_type::second++); }
|
||||
|
||||
// Pre-decrement operator.
|
||||
type&
|
||||
operator--()
|
||||
{
|
||||
--base_type::first;
|
||||
--base_type::second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Post-decrement operator.
|
||||
const type
|
||||
operator--(int)
|
||||
{ return type(base_type::first--, base_type::second--); }
|
||||
|
||||
// Type conversion.
|
||||
operator Iterator2() const
|
||||
{ return base_type::second; }
|
||||
|
||||
type&
|
||||
operator=(const type& other)
|
||||
{
|
||||
base_type::first = other.first;
|
||||
base_type::second = other.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
type
|
||||
operator+(difference_type delta) const
|
||||
{ return type(base_type::first + delta, base_type::second + delta); }
|
||||
|
||||
difference_type
|
||||
operator-(const type& other) const
|
||||
{ return base_type::first - other.first; }
|
||||
};
|
||||
|
||||
|
||||
/** @brief A triple of iterators. The usual iterator operations are
|
||||
applied to all three child iterators.
|
||||
*/
|
||||
template<typename Iterator1, typename Iterator2, typename Iterator3, typename IteratorCategory>
|
||||
class iterator_triple
|
||||
{
|
||||
private:
|
||||
typedef iterator_triple<Iterator1, Iterator2, Iterator3, IteratorCategory> type;
|
||||
|
||||
public:
|
||||
typedef IteratorCategory iterator_category;
|
||||
typedef void value_type;
|
||||
typedef typename Iterator1::difference_type difference_type;
|
||||
typedef type* pointer;
|
||||
typedef type& reference;
|
||||
|
||||
Iterator1 first;
|
||||
Iterator2 second;
|
||||
Iterator3 third;
|
||||
|
||||
iterator_triple() { }
|
||||
|
||||
iterator_triple(const Iterator1& _first, const Iterator2& _second,
|
||||
const Iterator3& _third)
|
||||
{
|
||||
first = _first;
|
||||
second = _second;
|
||||
third = _third;
|
||||
}
|
||||
|
||||
// Pre-increment operator.
|
||||
type&
|
||||
operator++()
|
||||
{
|
||||
++first;
|
||||
++second;
|
||||
++third;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Post-increment operator.
|
||||
const type
|
||||
operator++(int)
|
||||
{ return type(first++, second++, third++); }
|
||||
|
||||
// Pre-decrement operator.
|
||||
type&
|
||||
operator--()
|
||||
{
|
||||
--first;
|
||||
--second;
|
||||
--third;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Post-decrement operator.
|
||||
const type
|
||||
operator--(int)
|
||||
{ return type(first--, second--, third--); }
|
||||
|
||||
// Type conversion.
|
||||
operator Iterator3() const
|
||||
{ return third; }
|
||||
|
||||
type&
|
||||
operator=(const type& other)
|
||||
{
|
||||
first = other.first;
|
||||
second = other.second;
|
||||
third = other.third;
|
||||
return *this;
|
||||
}
|
||||
|
||||
type
|
||||
operator+(difference_type delta) const
|
||||
{ return type(first + delta, second + delta, third + delta); }
|
||||
|
||||
difference_type
|
||||
operator-(const type& other) const
|
||||
{ return first - other.first; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
181
libstdc++-v3/include/parallel/list_partition.h
Normal file
181
libstdc++-v3/include/parallel/list_partition.h
Normal file
@ -0,0 +1,181 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/list_partition.h
|
||||
* @brief Functionality to split sequence referenced by only input
|
||||
* iterators.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Leonor Frias Moya and Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_LIST_PARTITION_H
|
||||
#define _GLIBCXX_PARALLEL_LIST_PARTITION_H 1
|
||||
|
||||
#include <parallel/parallel.h>
|
||||
#include <vector>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @brief Shrinks and doubles the ranges.
|
||||
* @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
|
||||
* grown or not
|
||||
*/
|
||||
template<typename InputIterator>
|
||||
void
|
||||
shrink_and_double(std::vector<InputIterator>& os_starts, 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)
|
||||
{
|
||||
shrink(os_starts, count_to_two, range_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_starts.resize((os_starts.size() - 1) * 2 + 1);
|
||||
count_to_two = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Combines two ranges into one and thus halves the number of ranges.
|
||||
* @param os_starts Start positions worked on (oversampled).
|
||||
* @param count_to_two Counts up to 2.
|
||||
* @param range_length Current length of a chunk. */
|
||||
template<typename InputIterator>
|
||||
void
|
||||
shrink(std::vector<InputIterator>& os_starts, size_t& count_to_two,
|
||||
size_t& range_length)
|
||||
{
|
||||
for (typename std::vector<InputIterator>::size_type i = 0; i <= (os_starts.size() / 2); ++i)
|
||||
{
|
||||
os_starts[i] = os_starts[i * 2];
|
||||
}
|
||||
range_length *= 2;
|
||||
}
|
||||
|
||||
/** @brief Splits a sequence given by input iterators into parts of
|
||||
* almost equal size
|
||||
*
|
||||
* The function needs only one pass over the sequence.
|
||||
* @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]
|
||||
* 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$.
|
||||
* @return Length of the whole sequence.
|
||||
*/
|
||||
template<typename InputIterator, typename FunctorType>
|
||||
size_t
|
||||
list_partition(const InputIterator begin, const InputIterator end,
|
||||
InputIterator* starts, size_t* lengths, const int num_parts,
|
||||
FunctorType& f, int oversampling = 0)
|
||||
{
|
||||
bool make_twice = false;
|
||||
|
||||
// According to the oversampling factor, the resizing algorithm is chosen.
|
||||
if (oversampling == 0)
|
||||
{
|
||||
make_twice = true;
|
||||
oversampling = 1;
|
||||
}
|
||||
|
||||
std::vector<InputIterator> os_starts(2 * oversampling * num_parts + 1);
|
||||
|
||||
os_starts[0]= begin;
|
||||
InputIterator prev = begin, it = begin;
|
||||
size_t dist_limit = 0, dist = 0;
|
||||
size_t cur = 1, next = 1;
|
||||
size_t range_length = 1;
|
||||
size_t count_to_two = 0;
|
||||
while (it != end){
|
||||
cur = next;
|
||||
for (; cur < os_starts.size() and it != end; ++cur)
|
||||
{
|
||||
for (dist_limit += range_length; dist < dist_limit and it != end; ++dist)
|
||||
{
|
||||
f(it);
|
||||
++it;
|
||||
}
|
||||
os_starts[cur] = it;
|
||||
}
|
||||
|
||||
// Must compare for end and not cur < os_starts.size() , because
|
||||
// cur could be == os_starts.size() as well
|
||||
if (it == end)
|
||||
break;
|
||||
|
||||
shrink_and_double(os_starts, count_to_two, range_length, make_twice);
|
||||
next = os_starts.size()/2 + 1;
|
||||
}
|
||||
|
||||
// Calculation of the parts (one must be extracted from current
|
||||
// because the partition beginning at end, consists only of
|
||||
// itself).
|
||||
size_t size_part = (cur - 1) / num_parts;
|
||||
int size_greater = static_cast<int>((cur - 1) % num_parts);
|
||||
starts[0] = os_starts[0];
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
// Smallest partitions.
|
||||
for (int i = 1; i < (num_parts + 1 - size_greater); ++i)
|
||||
{
|
||||
lengths[i-1] = size_part * range_length;
|
||||
index += size_part;
|
||||
starts[i] = os_starts[index];
|
||||
}
|
||||
|
||||
// Biggest partitions.
|
||||
for (int i = num_parts + 1 - size_greater; i <= num_parts; ++i)
|
||||
{
|
||||
lengths[i-1] = (size_part+1) * range_length;
|
||||
index += (size_part+1);
|
||||
starts[i] = os_starts[index];
|
||||
}
|
||||
|
||||
// Correction of the end size (the end iteration has not finished).
|
||||
lengths[num_parts - 1] -= (dist_limit - dist);
|
||||
|
||||
return dist;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
1077
libstdc++-v3/include/parallel/losertree.h
Normal file
1077
libstdc++-v3/include/parallel/losertree.h
Normal file
File diff suppressed because it is too large
Load Diff
230
libstdc++-v3/include/parallel/merge.h
Normal file
230
libstdc++-v3/include/parallel/merge.h
Normal file
@ -0,0 +1,230 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/merge.h
|
||||
* @brief Parallel implementation of std::merge().
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_MERGE_H
|
||||
#define _GLIBCXX_PARALLEL_MERGE_H 1
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <bits/stl_algo.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @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.
|
||||
* @param begin1 Begin iterator of first sequence.
|
||||
* @param end1 End iterator of first sequence.
|
||||
* @param begin2 Begin iterator of second sequence.
|
||||
* @param end2 End iterator of second sequence.
|
||||
* @param target Target begin iterator.
|
||||
* @param max_length Maximum number of elements to merge.
|
||||
* @param comp Comparator.
|
||||
* @return Output end iterator. */
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename OutputIterator, typename _DifferenceTp, typename Comparator>
|
||||
OutputIterator
|
||||
merge_advance_usual(RandomAccessIterator1& begin1, RandomAccessIterator1 end1, RandomAccessIterator2& begin2, RandomAccessIterator2 end2, OutputIterator target, _DifferenceTp max_length, Comparator comp)
|
||||
{
|
||||
typedef _DifferenceTp difference_type;
|
||||
while (begin1 != end1 && begin2 != end2 && max_length > 0)
|
||||
{
|
||||
// array1[i1] < array0[i0]
|
||||
if (comp(*begin2, *begin1))
|
||||
*target++ = *begin2++;
|
||||
else
|
||||
*target++ = *begin1++;
|
||||
max_length--;
|
||||
}
|
||||
|
||||
if (begin1 != end1)
|
||||
{
|
||||
target = std::copy(begin1, begin1 + max_length, target);
|
||||
begin1 += max_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
target = std::copy(begin2, begin2 + max_length, target);
|
||||
begin2 += max_length;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/** @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.
|
||||
* Specially designed code should allow the compiler to generate
|
||||
* conditional moves instead of branches.
|
||||
* @param begin1 Begin iterator of first sequence.
|
||||
* @param end1 End iterator of first sequence.
|
||||
* @param begin2 Begin iterator of second sequence.
|
||||
* @param end2 End iterator of second sequence.
|
||||
* @param target Target begin iterator.
|
||||
* @param max_length Maximum number of elements to merge.
|
||||
* @param comp Comparator.
|
||||
* @return Output end iterator. */
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename OutputIterator, typename _DifferenceTp, typename Comparator>
|
||||
OutputIterator
|
||||
merge_advance_movc(RandomAccessIterator1& begin1, RandomAccessIterator1 end1, RandomAccessIterator2& begin2, RandomAccessIterator2 end2, OutputIterator target, _DifferenceTp max_length, Comparator comp)
|
||||
{
|
||||
typedef _DifferenceTp difference_type;
|
||||
typedef typename std::iterator_traits<RandomAccessIterator1>::value_type value_type1;
|
||||
typedef typename std::iterator_traits<RandomAccessIterator2>::value_type value_type2;
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_GLIBCXX_PARALLEL_ASSERT(max_length >= 0);
|
||||
#endif
|
||||
|
||||
while (begin1 != end1 && begin2 != end2 && max_length > 0)
|
||||
{
|
||||
value_type1 element1;
|
||||
value_type2 element2;
|
||||
RandomAccessIterator1 next1;
|
||||
RandomAccessIterator2 next2;
|
||||
|
||||
next1 = begin1 + 1;
|
||||
next2 = begin2 + 1;
|
||||
element1 = *begin1;
|
||||
element2 = *begin2;
|
||||
|
||||
if (comp(element2, element1))
|
||||
{
|
||||
element1 = element2;
|
||||
begin2 = next2;
|
||||
}
|
||||
else
|
||||
{
|
||||
begin1 = next1;
|
||||
}
|
||||
|
||||
*target = element1;
|
||||
|
||||
target++;
|
||||
max_length--;
|
||||
}
|
||||
if (begin1 != end1)
|
||||
{
|
||||
target = std::copy(begin1, begin1 + max_length, target);
|
||||
begin1 += max_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
target = std::copy(begin2, begin2 + max_length, target);
|
||||
begin2 += max_length;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/** @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.
|
||||
* Static switch on whether to use the conditional-move variant.
|
||||
* @param begin1 Begin iterator of first sequence.
|
||||
* @param end1 End iterator of first sequence.
|
||||
* @param begin2 Begin iterator of second sequence.
|
||||
* @param end2 End iterator of second sequence.
|
||||
* @param target Target begin iterator.
|
||||
* @param max_length Maximum number of elements to merge.
|
||||
* @param comp Comparator.
|
||||
* @return Output end iterator. */
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename OutputIterator, typename _DifferenceTp, typename Comparator>
|
||||
inline OutputIterator
|
||||
merge_advance(RandomAccessIterator1& begin1, RandomAccessIterator1 end1, RandomAccessIterator2& begin2, RandomAccessIterator2 end2, OutputIterator target, _DifferenceTp max_length, Comparator comp)
|
||||
{
|
||||
_GLIBCXX_CALL(max_length)
|
||||
|
||||
return merge_advance_movc(begin1, end1, begin2, end2, target, max_length, comp);
|
||||
}
|
||||
|
||||
/** @brief Merge routine fallback to sequential in case the
|
||||
iterators of the two input sequences are of different type.
|
||||
* @param begin1 Begin iterator of first sequence.
|
||||
* @param end1 End iterator of first sequence.
|
||||
* @param begin2 Begin iterator of second sequence.
|
||||
* @param end2 End iterator of second sequence.
|
||||
* @param target Target begin iterator.
|
||||
* @param max_length Maximum number of elements to merge.
|
||||
* @param comp Comparator.
|
||||
* @return Output end iterator. */
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename RandomAccessIterator3, typename Comparator>
|
||||
inline RandomAccessIterator3
|
||||
parallel_merge_advance(RandomAccessIterator1& begin1, RandomAccessIterator1 end1,
|
||||
RandomAccessIterator2& begin2, RandomAccessIterator2 end2, //different iterators, parallel implementation not available
|
||||
RandomAccessIterator3 target,
|
||||
typename std::iterator_traits<RandomAccessIterator1>::difference_type max_length, Comparator comp)
|
||||
{
|
||||
return merge_advance(begin1, end1, begin2, end2, target, max_length, comp);
|
||||
}
|
||||
|
||||
/** @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 functionality is projected onto parallel_multiway_merge.
|
||||
* @param begin1 Begin iterator of first sequence.
|
||||
* @param end1 End iterator of first sequence.
|
||||
* @param begin2 Begin iterator of second sequence.
|
||||
* @param end2 End iterator of second sequence.
|
||||
* @param target Target begin iterator.
|
||||
* @param max_length Maximum number of elements to merge.
|
||||
* @param comp Comparator.
|
||||
* @return Output end iterator.
|
||||
*/
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator3, typename Comparator>
|
||||
inline RandomAccessIterator3
|
||||
parallel_merge_advance(RandomAccessIterator1& begin1, RandomAccessIterator1 end1, RandomAccessIterator1& begin2, RandomAccessIterator1 end2, RandomAccessIterator3 target, typename std::iterator_traits<RandomAccessIterator1>::difference_type max_length, Comparator comp)
|
||||
{
|
||||
typedef typename std::iterator_traits<RandomAccessIterator1>::value_type
|
||||
value_type;
|
||||
typedef typename std::iterator_traits<RandomAccessIterator1>::difference_type
|
||||
difference_type1 /* == difference_type2 */;
|
||||
typedef typename std::iterator_traits<RandomAccessIterator3>::difference_type
|
||||
difference_type3;
|
||||
|
||||
std::pair<RandomAccessIterator1, RandomAccessIterator1> seqs[2] = { std::make_pair(begin1, end1), std::make_pair(begin2, end2) };
|
||||
RandomAccessIterator3 target_end = parallel_multiway_merge(seqs, seqs + 2, target, comp, max_length, true, false);
|
||||
|
||||
return target_end;
|
||||
}
|
||||
} //namespace __gnu_parallel
|
||||
|
||||
#endif
|
608
libstdc++-v3/include/parallel/multiseq_selection.h
Normal file
608
libstdc++-v3/include/parallel/multiseq_selection.h
Normal file
@ -0,0 +1,608 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/multiseq_selection.h
|
||||
* @brief Functions to find elements of a certain global rank in
|
||||
* multiple sorted sequences. Also serves for splitting such
|
||||
* sequence sets.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H
|
||||
#define _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H 1
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include <bits/stl_algo.h>
|
||||
|
||||
#include <parallel/sort.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @brief Compare a pair of types lexicographically, ascending. */
|
||||
template<typename T1, typename T2, typename Comparator>
|
||||
class lexicographic : public std::binary_function<std::pair<T1, T2>, std::pair<T1, T2>, bool>
|
||||
{
|
||||
private:
|
||||
Comparator& comp;
|
||||
|
||||
public:
|
||||
lexicographic(Comparator& _comp) : comp(_comp) { }
|
||||
|
||||
// XXX const
|
||||
inline bool
|
||||
operator()(const std::pair<T1, T2>& p1, const std::pair<T1, T2>& p2) const
|
||||
{
|
||||
if (comp(p1.first, p2.first))
|
||||
return true;
|
||||
|
||||
if (comp(p2.first, p1.first))
|
||||
return false;
|
||||
|
||||
// Firsts are equal.
|
||||
return p1.second < p2.second;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Compare a pair of types lexicographically, descending. */
|
||||
template<typename T1, typename T2, typename Comparator>
|
||||
class lexicographic_reverse : public std::binary_function<T1, T2, bool>
|
||||
{
|
||||
private:
|
||||
Comparator& comp;
|
||||
|
||||
public:
|
||||
lexicographic_reverse(Comparator& _comp) : comp(_comp) { }
|
||||
|
||||
inline bool
|
||||
operator()(const std::pair<T1, T2>& p1, const std::pair<T1, T2>& p2) const
|
||||
{
|
||||
if (comp(p2.first, p1.first))
|
||||
return true;
|
||||
|
||||
if (comp(p1.first, p2.first))
|
||||
return false;
|
||||
|
||||
// Firsts are equal.
|
||||
return p2.second < p1.second;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Splits several sorted sequences at a certain global rank,
|
||||
* resulting in a splitting point for each sequence.
|
||||
* The sequences are passed via a sequence of random-access
|
||||
* iterator pairs, none of the sequences may be empty. If there
|
||||
* are several equal elements across the split, the ones on the
|
||||
* left side will be chosen from sequences with smaller number.
|
||||
* @param begin_seqs Begin of the sequence of iterator pairs.
|
||||
* @param end_seqs End of the sequence of iterator pairs.
|
||||
* @param rank The global rank to partition at.
|
||||
* @param begin_offsets A random-access sequence begin where the
|
||||
* result will be stored in. Each element of the sequence is an
|
||||
* iterator that points to the first element on the greater part of
|
||||
* the respective sequence.
|
||||
* @param comp The ordering functor, defaults to std::less<T>.
|
||||
*/
|
||||
template<typename RanSeqs, typename RankType, typename RankIterator, typename Comparator>
|
||||
void
|
||||
multiseq_partition(RanSeqs begin_seqs, RanSeqs end_seqs, RankType rank,
|
||||
RankIterator begin_offsets,
|
||||
Comparator comp = std::less<
|
||||
typename std::iterator_traits<typename std::iterator_traits<RanSeqs>::value_type::first_type>::value_type>()) // std::less<T>
|
||||
{
|
||||
_GLIBCXX_CALL(end_seqs - begin_seqs)
|
||||
|
||||
typedef typename std::iterator_traits<RanSeqs>::value_type::first_type It;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef typename std::iterator_traits<It>::value_type T;
|
||||
|
||||
lexicographic<T, int, Comparator> lcomp(comp);
|
||||
lexicographic_reverse<T, int, Comparator> lrcomp(comp);
|
||||
|
||||
// Number of sequences, number of elements in total (possibly
|
||||
// including padding).
|
||||
difference_type m = std::distance(begin_seqs, end_seqs), N = 0, nmax, n, r;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
N += std::distance(begin_seqs[i].first, begin_seqs[i].second);
|
||||
|
||||
if (rank == N)
|
||||
{
|
||||
for (int i = 0; i < m; i++)
|
||||
begin_offsets[i] = begin_seqs[i].second; // Very end.
|
||||
// Return m - 1;
|
||||
}
|
||||
|
||||
_GLIBCXX_PARALLEL_ASSERT(m != 0 && N != 0 && rank >= 0 && rank < N);
|
||||
|
||||
difference_type* ns = new difference_type[m];
|
||||
difference_type* a = new difference_type[m];
|
||||
difference_type* b = new difference_type[m];
|
||||
difference_type l;
|
||||
|
||||
ns[0] = std::distance(begin_seqs[0].first, begin_seqs[0].second);
|
||||
nmax = ns[0];
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
ns[i] = std::distance(begin_seqs[i].first, begin_seqs[i].second);
|
||||
nmax = std::max(nmax, ns[i]);
|
||||
}
|
||||
|
||||
r = log2(nmax) + 1;
|
||||
|
||||
// Pad all lists to this length, at least as long as any ns[i],
|
||||
// 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;
|
||||
b[i] = l;
|
||||
}
|
||||
n = l / 2;
|
||||
|
||||
// Invariants:
|
||||
// 0 <= a[i] <= ns[i], 0 <= b[i] <= l
|
||||
|
||||
#define S(i) (begin_seqs[i].first)
|
||||
|
||||
// Initial partition.
|
||||
std::vector<std::pair<T, int> > sample;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
if (n < ns[i]) //sequence long enough
|
||||
sample.push_back(std::make_pair(S(i)[n], i));
|
||||
__gnu_sequential::sort(sample.begin(), sample.end(), lcomp);
|
||||
|
||||
for (int i = 0; i < m; i++) //conceptual infinity
|
||||
if (n >= ns[i]) //sequence too short, conceptual infinity
|
||||
sample.push_back(std::make_pair(S(i)[0] /*dummy element*/, i));
|
||||
|
||||
difference_type localrank = rank * m / N ;
|
||||
|
||||
int j;
|
||||
for (j = 0; j < localrank && ((n + 1) <= ns[sample[j].second]); j++)
|
||||
a[sample[j].second] += n + 1;
|
||||
for (; j < m; j++)
|
||||
b[sample[j].second] -= n + 1;
|
||||
|
||||
// Further refinement.
|
||||
while (n > 0)
|
||||
{
|
||||
n /= 2;
|
||||
|
||||
int lmax_seq = -1; // to avoid warning
|
||||
const T* lmax = NULL; // impossible to avoid the warning?
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
if (a[i] > 0)
|
||||
{
|
||||
if (!lmax)
|
||||
{
|
||||
lmax = &(S(i)[a[i] - 1]);
|
||||
lmax_seq = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max, favor rear sequences.
|
||||
if (!comp(S(i)[a[i] - 1], *lmax))
|
||||
{
|
||||
lmax = &(S(i)[a[i] - 1]);
|
||||
lmax_seq = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
difference_type middle = (b[i] + a[i]) / 2;
|
||||
if (lmax && middle < ns[i] &&
|
||||
lcomp(std::make_pair(S(i)[middle], i), std::make_pair(*lmax, lmax_seq)))
|
||||
a[i] = std::min(a[i] + n + 1, ns[i]);
|
||||
else
|
||||
b[i] -= n + 1;
|
||||
}
|
||||
|
||||
difference_type leftsize = 0, total = 0;
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
leftsize += a[i] / (n + 1);
|
||||
total += l / (n + 1);
|
||||
}
|
||||
|
||||
difference_type skew = static_cast<difference_type>(static_cast<uint64>(total) * rank / N - leftsize);
|
||||
|
||||
if (skew > 0)
|
||||
{
|
||||
// Move to the left, find smallest.
|
||||
std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int> >, lexicographic_reverse<T, int, Comparator> > pq(lrcomp);
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
if (b[i] < ns[i])
|
||||
pq.push(std::make_pair(S(i)[b[i]], i));
|
||||
|
||||
for (; skew != 0 && !pq.empty(); skew--)
|
||||
{
|
||||
int source = pq.top().second;
|
||||
pq.pop();
|
||||
|
||||
a[source] = std::min(a[source] + n + 1, ns[source]);
|
||||
b[source] += n + 1;
|
||||
|
||||
if (b[source] < ns[source])
|
||||
pq.push(std::make_pair(S(source)[b[source]], source));
|
||||
}
|
||||
}
|
||||
else if (skew < 0)
|
||||
{
|
||||
// Move to the right, find greatest.
|
||||
std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int> >, lexicographic<T, int, Comparator> > pq(lcomp);
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
if (a[i] > 0)
|
||||
pq.push(std::make_pair(S(i)[a[i] - 1], i));
|
||||
|
||||
for (; skew != 0; skew++)
|
||||
{
|
||||
int source = pq.top().second;
|
||||
pq.pop();
|
||||
|
||||
a[source] -= n + 1;
|
||||
b[source] -= n + 1;
|
||||
|
||||
if (a[source] > 0)
|
||||
pq.push(std::make_pair(S(source)[a[source] - 1], source));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Postconditions:
|
||||
// a[i] == b[i] in most cases, except when a[i] has been clamped
|
||||
// because of having reached the boundary
|
||||
|
||||
// Now return the result, calculate the offset.
|
||||
|
||||
// Compare the keys on both edges of the border.
|
||||
|
||||
// Maximum of left edge, minimum of right edge.
|
||||
bool maxleftset = false, minrightset = false;
|
||||
T maxleft, minright; // Impossible to avoid the warning?
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
if (a[i] > 0)
|
||||
{
|
||||
if (!maxleftset)
|
||||
{
|
||||
maxleft = S(i)[a[i] - 1];
|
||||
maxleftset = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max, favor rear sequences.
|
||||
if (!comp(S(i)[a[i] - 1], maxleft))
|
||||
maxleft = S(i)[a[i] - 1];
|
||||
}
|
||||
}
|
||||
if (b[i] < ns[i])
|
||||
{
|
||||
if (!minrightset)
|
||||
{
|
||||
minright = S(i)[b[i]];
|
||||
minrightset = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Min, favor fore sequences.
|
||||
if (comp(S(i)[b[i]], minright))
|
||||
minright = S(i)[b[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int seq = 0;
|
||||
for (int i = 0; i < m; i++)
|
||||
begin_offsets[i] = S(i) + a[i];
|
||||
|
||||
delete[] ns;
|
||||
delete[] a;
|
||||
delete[] b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Selects the element at a certain global rank from several
|
||||
* sorted sequences.
|
||||
*
|
||||
* The sequences are passed via a sequence of random-access
|
||||
* iterator pairs, none of the sequences may be empty.
|
||||
* @param begin_seqs Begin of the sequence of iterator pairs.
|
||||
* @param end_seqs End of the sequence of iterator pairs.
|
||||
* @param rank The global rank to partition at.
|
||||
* @param offset The rank of the selected element in the global
|
||||
* subsequence of elements equal to the selected element. If the
|
||||
* selected element is unique, this number is 0.
|
||||
* @param comp The ordering functor, defaults to std::less.
|
||||
*/
|
||||
template<typename T, typename RanSeqs, typename RankType, typename Comparator>
|
||||
T
|
||||
multiseq_selection(RanSeqs begin_seqs, RanSeqs end_seqs, RankType rank,
|
||||
RankType& offset, Comparator comp = std::less<T>())
|
||||
{
|
||||
_GLIBCXX_CALL(end_seqs - begin_seqs)
|
||||
|
||||
typedef typename std::iterator_traits<RanSeqs>::value_type::first_type It;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
|
||||
lexicographic<T, int, Comparator> lcomp(comp);
|
||||
lexicographic_reverse<T, int, Comparator> lrcomp(comp);
|
||||
|
||||
// Number of sequences, number of elements in total (possibly
|
||||
// including padding).
|
||||
difference_type m = std::distance(begin_seqs, end_seqs);
|
||||
difference_type N = 0;
|
||||
difference_type nmax, n, r;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
N += std::distance(begin_seqs[i].first, begin_seqs[i].second);
|
||||
|
||||
if (m == 0 || N == 0 || rank < 0 || rank >= N)
|
||||
{
|
||||
// Result undefined when there is no data or rank is outside bounds.
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
|
||||
difference_type* ns = new difference_type[m];
|
||||
difference_type* a = new difference_type[m];
|
||||
difference_type* b = new difference_type[m];
|
||||
difference_type l;
|
||||
|
||||
ns[0] = std::distance(begin_seqs[0].first, begin_seqs[0].second);
|
||||
nmax = ns[0];
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
ns[i] = std::distance(begin_seqs[i].first, begin_seqs[i].second);
|
||||
nmax = std::max(nmax, ns[i]);
|
||||
}
|
||||
|
||||
r = log2(nmax) + 1;
|
||||
|
||||
// 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;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
a[i] = 0;
|
||||
b[i] = l;
|
||||
}
|
||||
n = l / 2;
|
||||
|
||||
// Invariants:
|
||||
// 0 <= a[i] <= ns[i], 0 <= b[i] <= l
|
||||
|
||||
#define S(i) (begin_seqs[i].first)
|
||||
|
||||
// Initial partition.
|
||||
std::vector<std::pair<T, int> > sample;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
if (n < ns[i])
|
||||
sample.push_back(std::make_pair(S(i)[n], i));
|
||||
__gnu_sequential::sort(sample.begin(), sample.end(), lcomp, sequential_tag());
|
||||
|
||||
// Conceptual infinity.
|
||||
for (int i = 0; i < m; i++)
|
||||
if (n >= ns[i])
|
||||
sample.push_back(std::make_pair(S(i)[0] /*dummy element*/, i));
|
||||
|
||||
difference_type localrank = rank * m / N ;
|
||||
|
||||
int j;
|
||||
for (j = 0; j < localrank && ((n + 1) <= ns[sample[j].second]); j++)
|
||||
a[sample[j].second] += n + 1;
|
||||
for (; j < m; j++)
|
||||
b[sample[j].second] -= n + 1;
|
||||
|
||||
// Further refinement.
|
||||
while (n > 0)
|
||||
{
|
||||
n /= 2;
|
||||
|
||||
const T* lmax = NULL;
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
if (a[i] > 0)
|
||||
{
|
||||
if (!lmax)
|
||||
{
|
||||
lmax = &(S(i)[a[i] - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp(*lmax, S(i)[a[i] - 1])) //max
|
||||
lmax = &(S(i)[a[i] - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < m; i++)
|
||||
{
|
||||
difference_type middle = (b[i] + a[i]) / 2;
|
||||
if (lmax && middle < ns[i] && comp(S(i)[middle], *lmax))
|
||||
a[i] = std::min(a[i] + n + 1, ns[i]);
|
||||
else
|
||||
b[i] -= n + 1;
|
||||
}
|
||||
|
||||
difference_type leftsize = 0, total = 0;
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
leftsize += a[i] / (n + 1);
|
||||
total += l / (n + 1);
|
||||
}
|
||||
|
||||
difference_type skew = (unsigned long long)total * rank / N - leftsize;
|
||||
|
||||
if (skew > 0)
|
||||
{
|
||||
// Move to the left, find smallest.
|
||||
std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int> >, lexicographic_reverse<T, int, Comparator> > pq(lrcomp);
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
if (b[i] < ns[i])
|
||||
pq.push(std::make_pair(S(i)[b[i]], i));
|
||||
|
||||
for (; skew != 0 && !pq.empty(); skew--)
|
||||
{
|
||||
int source = pq.top().second;
|
||||
pq.pop();
|
||||
|
||||
a[source] = std::min(a[source] + n + 1, ns[source]);
|
||||
b[source] += n + 1;
|
||||
|
||||
if (b[source] < ns[source])
|
||||
pq.push(std::make_pair(S(source)[b[source]], source));
|
||||
}
|
||||
}
|
||||
else if (skew < 0)
|
||||
{
|
||||
// Move to the right, find greatest.
|
||||
std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int> >, lexicographic<T, int, Comparator> > pq(lcomp);
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
if (a[i] > 0)
|
||||
pq.push(std::make_pair(S(i)[a[i] - 1], i));
|
||||
|
||||
for (; skew != 0; skew++)
|
||||
{
|
||||
int source = pq.top().second;
|
||||
pq.pop();
|
||||
|
||||
a[source] -= n + 1;
|
||||
b[source] -= n + 1;
|
||||
|
||||
if (a[source] > 0)
|
||||
pq.push(std::make_pair(S(source)[a[source] - 1], source));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Postconditions:
|
||||
// a[i] == b[i] in most cases, except when a[i] has been clamped
|
||||
// because of having reached the boundary
|
||||
|
||||
// Now return the result, calculate the offset.
|
||||
|
||||
// Compare the keys on both edges of the border.
|
||||
|
||||
// Maximum of left edge, minimum of right edge.
|
||||
bool maxleftset = false, minrightset = false;
|
||||
|
||||
// Impossible to avoid the warning?
|
||||
T maxleft, minright;
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
if (a[i] > 0)
|
||||
{
|
||||
if (!maxleftset)
|
||||
{
|
||||
maxleft = S(i)[a[i] - 1];
|
||||
maxleftset = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max.
|
||||
if (comp(maxleft, S(i)[a[i] - 1]))
|
||||
maxleft = S(i)[a[i] - 1];
|
||||
}
|
||||
}
|
||||
if (b[i] < ns[i])
|
||||
{
|
||||
if (!minrightset)
|
||||
{
|
||||
minright = S(i)[b[i]];
|
||||
minrightset = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Min.
|
||||
if (comp(S(i)[b[i]], minright))
|
||||
minright = S(i)[b[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Minright is the splitter, in any case.
|
||||
|
||||
if (!maxleftset || comp(minright, maxleft))
|
||||
{
|
||||
// Good luck, everything is split unambigiously.
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have to calculate an offset.
|
||||
offset = 0;
|
||||
|
||||
for (int i = 0; i < m; i++)
|
||||
{
|
||||
difference_type lb = std::lower_bound(S(i), S(i) + ns[i], minright,
|
||||
comp) - S(i);
|
||||
offset += a[i] - lb;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] ns;
|
||||
delete[] a;
|
||||
delete[] b;
|
||||
|
||||
return minright;
|
||||
}
|
||||
}
|
||||
|
||||
#undef S
|
||||
|
||||
#endif
|
||||
|
1639
libstdc++-v3/include/parallel/multiway_merge.h
Normal file
1639
libstdc++-v3/include/parallel/multiway_merge.h
Normal file
File diff suppressed because it is too large
Load Diff
413
libstdc++-v3/include/parallel/multiway_mergesort.h
Normal file
413
libstdc++-v3/include/parallel/multiway_mergesort.h
Normal file
@ -0,0 +1,413 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/multiway_mergesort.h
|
||||
* @brief Parallel multiway merge sort.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_MERGESORT_H
|
||||
#define _GLIBCXX_PARALLEL_MERGESORT_H 1
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <bits/stl_algo.h>
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/multiway_merge.h>
|
||||
#include <parallel/timing.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
|
||||
/** @brief Subsequence description. */
|
||||
template<typename _DifferenceTp>
|
||||
struct Piece
|
||||
{
|
||||
typedef _DifferenceTp difference_type;
|
||||
|
||||
/** @brief Begin of subsequence. */
|
||||
difference_type begin;
|
||||
|
||||
/** @brief End of subsequence. */
|
||||
difference_type end;
|
||||
};
|
||||
|
||||
/** @brief Data accessed by all threads.
|
||||
*
|
||||
* PMWMS = parallel multiway mergesort */
|
||||
template<typename RandomAccessIterator>
|
||||
struct PMWMSSortingData
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
/** @brief Input begin. */
|
||||
RandomAccessIterator source;
|
||||
|
||||
/** @brief Start indices, per thread. */
|
||||
difference_type* starts;
|
||||
|
||||
/** @brief Temporary arrays for each thread.
|
||||
*
|
||||
* Indirection Allows using the temporary storage in different
|
||||
* ways, without code duplication.
|
||||
* @see _GLIBCXX_MULTIWAY_MERGESORT_COPY_LAST */
|
||||
value_type** temporaries;
|
||||
|
||||
#if _GLIBCXX_MULTIWAY_MERGESORT_COPY_LAST
|
||||
/** @brief Storage in which to sort. */
|
||||
RandomAccessIterator* sorting_places;
|
||||
|
||||
/** @brief Storage into which to merge. */
|
||||
value_type** merging_places;
|
||||
#else
|
||||
/** @brief Storage in which to sort. */
|
||||
value_type** sorting_places;
|
||||
|
||||
/** @brief Storage into which to merge. */
|
||||
RandomAccessIterator* merging_places;
|
||||
#endif
|
||||
/** @brief Samples. */
|
||||
value_type* samples;
|
||||
|
||||
/** @brief Offsets to add to the found positions. */
|
||||
difference_type* offsets;
|
||||
|
||||
/** @brief Pieces of data to merge @c [thread][sequence] */
|
||||
std::vector<Piece<difference_type> >* pieces;
|
||||
};
|
||||
|
||||
/** @brief Thread local data for PMWMS. */
|
||||
template<typename RandomAccessIterator>
|
||||
struct PMWMSSorterPU
|
||||
{
|
||||
/** @brief Total number of thread involved. */
|
||||
thread_index_t num_threads;
|
||||
/** @brief Number of owning thread. */
|
||||
thread_index_t iam;
|
||||
/** @brief Stable sorting desired. */
|
||||
bool stable;
|
||||
/** @brief Pointer to global data. */
|
||||
PMWMSSortingData<RandomAccessIterator>* sd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Select samples from a sequence.
|
||||
* @param d Pointer to thread-local data. Result will be placed in
|
||||
* @c d->ds->samples.
|
||||
* @param num_samples Number of samples to select.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename _DifferenceTp>
|
||||
inline void
|
||||
determine_samples(PMWMSSorterPU<RandomAccessIterator>* d,
|
||||
_DifferenceTp& num_samples)
|
||||
{
|
||||
typedef _DifferenceTp difference_type;
|
||||
|
||||
PMWMSSortingData<RandomAccessIterator>* sd = d->sd;
|
||||
|
||||
num_samples = Settings::sort_mwms_oversampling * d->num_threads - 1;
|
||||
|
||||
difference_type es[num_samples + 2];
|
||||
equally_split(sd->starts[d->iam + 1] - sd->starts[d->iam], num_samples + 1, es);
|
||||
|
||||
for (difference_type i = 0; i < num_samples; i++)
|
||||
sd->samples[d->iam * num_samples + i] = sd->source[sd->starts[d->iam] + es[i + 1]];
|
||||
}
|
||||
|
||||
/** @brief PMWMS code executed by each thread.
|
||||
* @param d Pointer to thread-local data.
|
||||
* @param comp Comparator.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
parallel_sort_mwms_pu(PMWMSSorterPU<RandomAccessIterator>* d,
|
||||
Comparator& comp)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
Timing<sequential_tag> t;
|
||||
|
||||
t.tic();
|
||||
|
||||
PMWMSSortingData<RandomAccessIterator>* sd = d->sd;
|
||||
thread_index_t iam = d->iam;
|
||||
|
||||
// Length of this thread's chunk, before merging.
|
||||
difference_type length_local = sd->starts[iam + 1] - sd->starts[iam];
|
||||
|
||||
#if _GLIBCXX_MULTIWAY_MERGESORT_COPY_LAST
|
||||
typedef RandomAccessIterator SortingPlacesIterator;
|
||||
|
||||
// Sort in input storage.
|
||||
sd->sorting_places[iam] = sd->source + sd->starts[iam];
|
||||
#else
|
||||
typedef value_type* SortingPlacesIterator;
|
||||
|
||||
// Sort in temporary storage, leave space for sentinel.
|
||||
sd->sorting_places[iam] = sd->temporaries[iam] = static_cast<value_type*>(::operator new(sizeof(value_type) *(length_local + 1)));
|
||||
|
||||
// Copy there.
|
||||
std::uninitialized_copy(sd->source + sd->starts[iam], sd->source + sd->starts[iam] + length_local, sd->sorting_places[iam]);
|
||||
#endif
|
||||
|
||||
// Sort locally.
|
||||
if (d->stable)
|
||||
__gnu_sequential::stable_sort(sd->sorting_places[iam], sd->sorting_places[iam] + length_local, comp);
|
||||
else
|
||||
__gnu_sequential::sort(sd->sorting_places[iam], sd->sorting_places[iam] + length_local, comp);
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_GLIBCXX_PARALLEL_ASSERT(is_sorted(sd->sorting_places[iam], sd->sorting_places[iam] + length_local, comp));
|
||||
#endif
|
||||
|
||||
// Invariant: locally sorted subsequence in sd->sorting_places[iam],
|
||||
// sd->sorting_places[iam] + length_local.
|
||||
t.tic("local sort");
|
||||
|
||||
if (Settings::sort_splitting == Settings::SAMPLING)
|
||||
{
|
||||
difference_type num_samples;
|
||||
determine_samples(d, num_samples);
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic("sample/wait");
|
||||
|
||||
#pragma omp single
|
||||
__gnu_sequential::sort(sd->samples, sd->samples + (num_samples * d->num_threads), comp);
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
for (int s = 0; s < d->num_threads; s++)
|
||||
{
|
||||
// For each sequence.
|
||||
if (num_samples * iam > 0)
|
||||
sd->pieces[iam][s].begin = std::lower_bound(sd->sorting_places[s],
|
||||
sd->sorting_places[s] + sd->starts[s + 1] - sd->starts[s],
|
||||
sd->samples[num_samples * iam],
|
||||
comp)
|
||||
- sd->sorting_places[s];
|
||||
else
|
||||
// Absolute beginning.
|
||||
sd->pieces[iam][s].begin = 0;
|
||||
|
||||
if ((num_samples * (iam + 1)) < (num_samples * d->num_threads))
|
||||
sd->pieces[iam][s].end = std::lower_bound(sd->sorting_places[s],
|
||||
sd->sorting_places[s] + sd->starts[s + 1] - sd->starts[s], sd->samples[num_samples * (iam + 1)], comp)
|
||||
- sd->sorting_places[s];
|
||||
else
|
||||
// Absolute end.
|
||||
sd->pieces[iam][s].end = sd->starts[s + 1] - sd->starts[s];
|
||||
}
|
||||
|
||||
}
|
||||
else if (Settings::sort_splitting == Settings::EXACT)
|
||||
{
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic("wait");
|
||||
|
||||
std::vector<std::pair<SortingPlacesIterator, SortingPlacesIterator> > seqs(d->num_threads);
|
||||
for (int s = 0; s < d->num_threads; s++)
|
||||
seqs[s] = std::make_pair(sd->sorting_places[s], sd->sorting_places[s] + sd->starts[s + 1] - sd->starts[s]);
|
||||
|
||||
std::vector<SortingPlacesIterator> offsets(d->num_threads);
|
||||
|
||||
// If not last thread.
|
||||
if (iam < d->num_threads - 1)
|
||||
multiseq_partition(seqs.begin(), seqs.end(), sd->starts[iam + 1], offsets.begin(), comp);
|
||||
|
||||
for (int seq = 0; seq < d->num_threads; seq++)
|
||||
{
|
||||
// For each sequence.
|
||||
if (iam < (d->num_threads - 1))
|
||||
sd->pieces[iam][seq].end = offsets[seq] - seqs[seq].first;
|
||||
else
|
||||
// Absolute end of this sequence.
|
||||
sd->pieces[iam][seq].end = sd->starts[seq + 1] - sd->starts[seq];
|
||||
}
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
for (int seq = 0; seq < d->num_threads; seq++)
|
||||
{
|
||||
// For each sequence.
|
||||
if (iam > 0)
|
||||
sd->pieces[iam][seq].begin = sd->pieces[iam - 1][seq].end;
|
||||
else
|
||||
// Absolute beginning.
|
||||
sd->pieces[iam][seq].begin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
t.tic("split");
|
||||
|
||||
// Offset from target begin, length after merging.
|
||||
difference_type offset = 0, length_am = 0;
|
||||
for (int s = 0; s < d->num_threads; s++)
|
||||
{
|
||||
length_am += sd->pieces[iam][s].end - sd->pieces[iam][s].begin;
|
||||
offset += sd->pieces[iam][s].begin;
|
||||
}
|
||||
|
||||
#if _GLIBCXX_MULTIWAY_MERGESORT_COPY_LAST
|
||||
// Merge to temporary storage, uninitialized creation not possible
|
||||
// since there is no multiway_merge calling the placement new
|
||||
// instead of the assignment operator.
|
||||
sd->merging_places[iam] = sd->temporaries[iam] = new value_type[length_am];
|
||||
#else
|
||||
// Merge directly to target.
|
||||
sd->merging_places[iam] = sd->source + offset;
|
||||
#endif
|
||||
std::vector<std::pair<SortingPlacesIterator, SortingPlacesIterator> > seqs(d->num_threads);
|
||||
|
||||
for (int s = 0; s < d->num_threads; s++)
|
||||
{
|
||||
seqs[s] = std::make_pair(sd->sorting_places[s] + sd->pieces[iam][s].begin, sd->sorting_places[s] + sd->pieces[iam][s].end);
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_GLIBCXX_PARALLEL_ASSERT(is_sorted(seqs[s].first, seqs[s].second, comp));
|
||||
#endif
|
||||
}
|
||||
|
||||
multiway_merge(seqs.begin(), seqs.end(), sd->merging_places[iam], comp, length_am, d->stable, false, sequential_tag());
|
||||
|
||||
t.tic("merge");
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_GLIBCXX_PARALLEL_ASSERT(is_sorted(sd->merging_places[iam], sd->merging_places[iam] + length_am, comp));
|
||||
#endif
|
||||
|
||||
# pragma omp barrier
|
||||
|
||||
#if _GLIBCXX_MULTIWAY_MERGESORT_COPY_LAST
|
||||
// Write back.
|
||||
std::copy(sd->merging_places[iam], sd->merging_places[iam] + length_am,
|
||||
sd->source + offset);
|
||||
#endif
|
||||
|
||||
delete[] sd->temporaries[iam];
|
||||
|
||||
t.tic("copy back");
|
||||
|
||||
t.print();
|
||||
}
|
||||
|
||||
/** @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.
|
||||
* @param stable Stable sorting.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
parallel_sort_mwms(RandomAccessIterator begin, RandomAccessIterator end, Comparator comp, typename std::iterator_traits<RandomAccessIterator>::difference_type n, int num_threads, bool stable)
|
||||
{
|
||||
_GLIBCXX_CALL(n)
|
||||
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
// At least one element per thread.
|
||||
if (num_threads > n)
|
||||
num_threads = static_cast<thread_index_t>(n);
|
||||
|
||||
PMWMSSortingData<RandomAccessIterator> sd;
|
||||
|
||||
sd.source = begin;
|
||||
sd.temporaries = new value_type*[num_threads];
|
||||
|
||||
#if _GLIBCXX_MULTIWAY_MERGESORT_COPY_LAST
|
||||
sd.sorting_places = new RandomAccessIterator[num_threads];
|
||||
sd.merging_places = new value_type*[num_threads];
|
||||
#else
|
||||
sd.sorting_places = new value_type*[num_threads];
|
||||
sd.merging_places = new RandomAccessIterator[num_threads];
|
||||
#endif
|
||||
|
||||
if (Settings::sort_splitting == Settings::SAMPLING)
|
||||
sd.samples = new value_type[num_threads * (Settings::sort_mwms_oversampling * num_threads - 1)];
|
||||
else
|
||||
sd.samples = NULL;
|
||||
|
||||
sd.offsets = new difference_type[num_threads - 1];
|
||||
sd.pieces = new std::vector<Piece<difference_type> >[num_threads];
|
||||
for (int s = 0; s < num_threads; s++)
|
||||
sd.pieces[s].resize(num_threads);
|
||||
PMWMSSorterPU<RandomAccessIterator>* pus = new PMWMSSorterPU<RandomAccessIterator>[num_threads];
|
||||
difference_type* starts = sd.starts = new difference_type[num_threads + 1];
|
||||
|
||||
difference_type chunk_length = n / num_threads, split = n % num_threads, start = 0;
|
||||
for (int i = 0; i < num_threads; i++)
|
||||
{
|
||||
starts[i] = start;
|
||||
start += (i < split) ? (chunk_length + 1) : chunk_length;
|
||||
pus[i].num_threads = num_threads;
|
||||
pus[i].iam = i;
|
||||
pus[i].sd = &sd;
|
||||
pus[i].stable = stable;
|
||||
}
|
||||
starts[num_threads] = start;
|
||||
|
||||
// Now sort in parallel.
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
parallel_sort_mwms_pu(&(pus[omp_get_thread_num()]), comp);
|
||||
|
||||
// XXX sd as RAII
|
||||
delete[] starts;
|
||||
delete[] sd.temporaries;
|
||||
delete[] sd.sorting_places;
|
||||
delete[] sd.merging_places;
|
||||
|
||||
if (Settings::sort_splitting == Settings::SAMPLING)
|
||||
delete[] sd.samples;
|
||||
|
||||
delete[] sd.offsets;
|
||||
delete[] sd.pieces;
|
||||
|
||||
delete[] pus;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
322
libstdc++-v3/include/parallel/numeric
Normal file
322
libstdc++-v3/include/parallel/numeric
Normal file
@ -0,0 +1,322 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/**
|
||||
* @file parallel/numeric
|
||||
*
|
||||
* @brief Parallel STL fucntion calls corresponding to stl_numeric.h.
|
||||
* The functions defined here mainly do case switches and
|
||||
* call the actual parallelized versions in other files.
|
||||
* Inlining policy: Functions that basically only contain one function call,
|
||||
* are declared inline.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler and Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_NUMERIC_H
|
||||
#define _GLIBCXX_PARALLEL_NUMERIC_H 1
|
||||
|
||||
#include <numeric>
|
||||
#include <functional>
|
||||
#include <parallel/numericfwd.h>
|
||||
#include <parallel/iterator.h>
|
||||
#include <parallel/for_each.h>
|
||||
#include <parallel/for_each_selectors.h>
|
||||
#include <parallel/partial_sum.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace __parallel
|
||||
{
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator, typename T>
|
||||
inline T
|
||||
accumulate(InputIterator begin, InputIterator end, T init, __gnu_parallel::sequential_tag)
|
||||
{ return _GLIBCXX_STD_P::accumulate(begin, end, init); }
|
||||
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator, typename T, typename BinaryOperation>
|
||||
inline T
|
||||
accumulate(InputIterator begin, InputIterator end, T init,
|
||||
BinaryOperation binary_op, __gnu_parallel::sequential_tag)
|
||||
{ return _GLIBCXX_STD_P::accumulate(begin, end, init, binary_op); }
|
||||
|
||||
// Sequential fallback for input iterator case.
|
||||
template<typename InputIterator, typename T, typename IteratorTag>
|
||||
inline T
|
||||
accumulate_switch(InputIterator begin, InputIterator end, T init, IteratorTag, __gnu_parallel::parallelism parallelism_tag)
|
||||
{ return accumulate(begin, end, init, __gnu_parallel::sequential_tag()); }
|
||||
|
||||
// Public interface.
|
||||
template<typename InputIterator, typename T>
|
||||
inline T
|
||||
accumulate(InputIterator begin, InputIterator end, T init, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced)
|
||||
{
|
||||
return accumulate_switch(begin, end, init, std::plus<typename std::iterator_traits<InputIterator>::value_type>(), typename std::iterator_traits<InputIterator>::iterator_category(), parallelism_tag);
|
||||
}
|
||||
|
||||
// Sequential fallback for input iterator case.
|
||||
template<typename InputIterator, typename T, typename BinaryOperation, typename IteratorTag>
|
||||
T
|
||||
accumulate_switch(InputIterator begin, InputIterator end, T init, BinaryOperation binary_op, IteratorTag, __gnu_parallel::parallelism parallelism_tag)
|
||||
{
|
||||
return accumulate(begin, end, init, binary_op, __gnu_parallel::sequential_tag());
|
||||
}
|
||||
|
||||
// Parallel algorithm for random access iterators.
|
||||
template<typename _RandomAccessIterator, typename T, typename BinaryOperation>
|
||||
T
|
||||
accumulate_switch(_RandomAccessIterator begin, _RandomAccessIterator end, T init, BinaryOperation binary_op, random_access_iterator_tag, __gnu_parallel::parallelism parallelism_tag)
|
||||
{
|
||||
if (_GLIBCXX_PARALLEL_CONDITION(static_cast<__gnu_parallel::sequence_index_t>(end - begin) >= __gnu_parallel::Settings::accumulate_minimal_n && __gnu_parallel::is_parallel(parallelism_tag)))
|
||||
{
|
||||
T res = init;
|
||||
__gnu_parallel::accumulate_selector<_RandomAccessIterator> my_selector;
|
||||
__gnu_parallel::for_each_template_random_access(begin, end, __gnu_parallel::nothing(), my_selector, __gnu_parallel::accumulate_binop_reduct<BinaryOperation>(binary_op), res, res, -1, parallelism_tag);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return accumulate(begin, end, init, binary_op, __gnu_parallel::sequential_tag());
|
||||
}
|
||||
|
||||
// Public interface.
|
||||
template<typename InputIterator, typename T, typename BinaryOperation>
|
||||
inline T
|
||||
accumulate(InputIterator begin, InputIterator end, T init, BinaryOperation binary_op, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced)
|
||||
{
|
||||
return accumulate_switch(begin, end, init, binary_op, typename std::iterator_traits<InputIterator>::iterator_category(), parallelism_tag);
|
||||
}
|
||||
|
||||
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator1, typename InputIterator2, typename T, typename BinaryFunction1, typename BinaryFunction2>
|
||||
inline T
|
||||
inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, __gnu_parallel::sequential_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init, binary_op1, binary_op2);
|
||||
}
|
||||
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator1, typename InputIterator2, typename T>
|
||||
inline T
|
||||
inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, __gnu_parallel::sequential_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init);
|
||||
}
|
||||
|
||||
// Parallel algorithm for random access iterators.
|
||||
template<typename RandomAccessIterator1, typename RandomAccessIterator2, typename T, typename BinaryFunction1, typename BinaryFunction2>
|
||||
T
|
||||
inner_product_switch(RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, random_access_iterator_tag, random_access_iterator_tag, __gnu_parallel::parallelism parallelism_tag)
|
||||
{
|
||||
if (_GLIBCXX_PARALLEL_CONDITION((last1 - first1) >= __gnu_parallel::Settings::accumulate_minimal_n && __gnu_parallel::is_parallel(parallelism_tag)))
|
||||
{
|
||||
T res = init;
|
||||
__gnu_parallel::inner_product_selector<RandomAccessIterator1, RandomAccessIterator2, T> my_selector(first1, first2);
|
||||
__gnu_parallel::for_each_template_random_access(first1, last1, binary_op2, my_selector, binary_op1, res, res, -1, parallelism_tag);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
return inner_product(first1, last1, first2, init, __gnu_parallel::sequential_tag());
|
||||
}
|
||||
|
||||
// No parallelism for input iterators.
|
||||
template<typename InputIterator1, typename InputIterator2, typename T, typename BinaryFunction1, typename BinaryFunction2, typename IteratorTag1, typename IteratorTag2>
|
||||
inline T
|
||||
inner_product_switch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, IteratorTag1, IteratorTag2, __gnu_parallel::parallelism parallelism_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init, binary_op1, binary_op2);
|
||||
}
|
||||
|
||||
template<typename InputIterator1, typename InputIterator2, typename T, typename BinaryFunction1, typename BinaryFunction2>
|
||||
inline T
|
||||
inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 binary_op1, BinaryFunction2 binary_op2, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced)
|
||||
{
|
||||
typedef iterator_traits<InputIterator1> traits1_type;
|
||||
typedef typename traits1_type::iterator_category iterator1_category;
|
||||
|
||||
typedef iterator_traits<InputIterator2> traits2_type;
|
||||
typedef typename traits2_type::iterator_category iterator2_category;
|
||||
|
||||
return inner_product_switch(first1, last1, first2, init, binary_op1, binary_op2, iterator1_category(), iterator2_category(), parallelism_tag);
|
||||
}
|
||||
|
||||
template<typename InputIterator1, typename InputIterator2, typename T>
|
||||
inline T
|
||||
inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced)
|
||||
{
|
||||
typedef iterator_traits<InputIterator1> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
|
||||
return inner_product(first1, last1, first2, init, std::plus<value_type>(),
|
||||
std::multiplies<value_type>(), parallelism_tag);
|
||||
}
|
||||
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
|
||||
__gnu_parallel::sequential_tag)
|
||||
{ return _GLIBCXX_STD_P::partial_sum(begin, end, result); }
|
||||
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
inline OutputIterator
|
||||
partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
|
||||
BinaryOperation bin_op, __gnu_parallel::sequential_tag)
|
||||
{ return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op); }
|
||||
|
||||
// Sequential fallback for input iterator case.
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation, typename IteratorTag1, typename IteratorTag2>
|
||||
inline OutputIterator
|
||||
partial_sum_switch(InputIterator begin, InputIterator end, OutputIterator result, BinaryOperation bin_op, IteratorTag1, IteratorTag2)
|
||||
{
|
||||
return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op);
|
||||
}
|
||||
|
||||
// Parallel algorithm for random access iterators.
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
OutputIterator
|
||||
partial_sum_switch(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation bin_op,
|
||||
random_access_iterator_tag, random_access_iterator_tag)
|
||||
{
|
||||
if (_GLIBCXX_PARALLEL_CONDITION(static_cast<__gnu_parallel::sequence_index_t>(end - begin) >= __gnu_parallel::Settings::partial_sum_minimal_n))
|
||||
return __gnu_parallel::parallel_partial_sum(begin, end, result, bin_op);
|
||||
else
|
||||
return partial_sum(begin, end, result, bin_op, __gnu_parallel::sequential_tag());
|
||||
}
|
||||
|
||||
// Public interface.
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
partial_sum(InputIterator begin, InputIterator end, OutputIterator result)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator>::value_type value_type;
|
||||
return partial_sum(begin, end, result, std::plus<value_type>());
|
||||
}
|
||||
|
||||
// Public interface
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
inline OutputIterator
|
||||
partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
|
||||
BinaryOperation binary_op)
|
||||
{
|
||||
typedef iterator_traits<InputIterator> traitsi_type;
|
||||
typedef typename traitsi_type::iterator_category iteratori_category;
|
||||
|
||||
typedef iterator_traits<OutputIterator> traitso_type;
|
||||
typedef typename traitso_type::iterator_category iteratoro_category;
|
||||
|
||||
return partial_sum_switch(begin, end, result, binary_op,
|
||||
iteratori_category(), iteratoro_category());
|
||||
}
|
||||
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
adjacent_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, __gnu_parallel::sequential_tag)
|
||||
{ return _GLIBCXX_STD_P::adjacent_difference(begin, end, result); }
|
||||
|
||||
// Sequential fallback.
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
inline OutputIterator
|
||||
adjacent_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation bin_op,
|
||||
__gnu_parallel::sequential_tag)
|
||||
{
|
||||
return _GLIBCXX_STD_P::adjacent_difference(begin, end, result, bin_op);
|
||||
}
|
||||
|
||||
// Sequential fallback for input iterator case.
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation, typename IteratorTag1, typename IteratorTag2>
|
||||
inline OutputIterator
|
||||
adjacent_difference_switch(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation bin_op,
|
||||
IteratorTag1, IteratorTag2, __gnu_parallel::parallelism)
|
||||
{ return adjacent_difference(begin, end, result, bin_op); }
|
||||
|
||||
// Parallel algorithm for random access iterators.
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
OutputIterator
|
||||
adjacent_difference_switch(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation bin_op,
|
||||
random_access_iterator_tag, random_access_iterator_tag,
|
||||
__gnu_parallel::parallelism parallelism_tag)
|
||||
{
|
||||
if (_GLIBCXX_PARALLEL_CONDITION(static_cast<__gnu_parallel::sequence_index_t>(end - begin) >= __gnu_parallel::Settings::adjacent_difference_minimal_n && __gnu_parallel::is_parallel(parallelism_tag)))
|
||||
{
|
||||
bool dummy = true;
|
||||
typedef __gnu_parallel::iterator_pair<InputIterator, OutputIterator, random_access_iterator_tag> ip;
|
||||
*result = *begin;
|
||||
ip begin_pair(begin + 1, result + 1), end_pair(end, result + (end - begin));
|
||||
__gnu_parallel::adjacent_difference_selector<ip> functionality;
|
||||
__gnu_parallel::for_each_template_random_access(begin_pair, end_pair, bin_op, functionality, __gnu_parallel::dummy_reduct(), dummy, dummy, -1, parallelism_tag);
|
||||
return functionality.finish_iterator;
|
||||
}
|
||||
else
|
||||
return adjacent_difference(begin, end, result, bin_op, __gnu_parallel::sequential_tag());
|
||||
}
|
||||
|
||||
// Public interface.
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
adjacent_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator result,
|
||||
__gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced)
|
||||
{
|
||||
typedef iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
return adjacent_difference(begin, end, result, std::minus<value_type>());
|
||||
}
|
||||
|
||||
// Public interface.
|
||||
template<typename InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
inline OutputIterator
|
||||
adjacent_difference(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation binary_op,
|
||||
__gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced)
|
||||
{
|
||||
typedef iterator_traits<InputIterator> traitsi_type;
|
||||
typedef typename traitsi_type::iterator_category iteratori_category;
|
||||
|
||||
typedef iterator_traits<OutputIterator> traitso_type;
|
||||
typedef typename traitso_type::iterator_category iteratoro_category;
|
||||
|
||||
return adjacent_difference_switch(begin, end, result, binary_op,
|
||||
iteratori_category(),
|
||||
iteratoro_category(), parallelism_tag);
|
||||
}
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif /* _GLIBCXX_NUMERIC_H */
|
152
libstdc++-v3/include/parallel/numericfwd.h
Normal file
152
libstdc++-v3/include/parallel/numericfwd.h
Normal file
@ -0,0 +1,152 @@
|
||||
// <numeric> parallel extensions -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/numericfwd.h
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_NUMERICFWD_H
|
||||
#define _GLIBCXX_PARALLEL_NUMERICFWD_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <parallel/tags.h>
|
||||
#include <parallel/settings.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace __parallel
|
||||
{
|
||||
template<typename _IIter, typename T>
|
||||
inline T
|
||||
accumulate(_IIter, _IIter, T, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename T, typename _BinaryOper>
|
||||
inline T
|
||||
accumulate(_IIter, _IIter, T, _BinaryOper, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename T>
|
||||
inline T
|
||||
accumulate(_IIter, _IIter, T, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced);
|
||||
|
||||
template<typename _IIter, typename T, typename _BinaryOper>
|
||||
inline T
|
||||
accumulate(_IIter, _IIter, T, _BinaryOper, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced);
|
||||
|
||||
template<typename _IIter, typename T, typename _Tag>
|
||||
inline T
|
||||
accumulate_switch(_IIter, _IIter, T, _Tag, __gnu_parallel::parallelism parallelism_tag);
|
||||
|
||||
template<typename _IIter, typename T, typename _BinaryOper, typename _Tag>
|
||||
T
|
||||
accumulate_switch(_IIter, _IIter, T, _BinaryOper, _Tag, __gnu_parallel::parallelism parallelism_tag);
|
||||
|
||||
template<typename _RAIter, typename T, typename _BinaryOper>
|
||||
T
|
||||
accumulate_switch(_RAIter, _RAIter, T, _BinaryOper, random_access_iterator_tag, __gnu_parallel::parallelism parallelism_tag);
|
||||
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
inline _OIter
|
||||
adjacent_difference(_IIter, _IIter, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper>
|
||||
inline _OIter
|
||||
adjacent_difference(_IIter, _IIter, _OIter, _BinaryOper, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
inline _OIter
|
||||
adjacent_difference(_IIter, _IIter, _OIter, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper>
|
||||
inline _OIter
|
||||
adjacent_difference(_IIter, _IIter, _OIter, _BinaryOper, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_balanced);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper, typename _Tag1, typename _Tag2>
|
||||
inline _OIter
|
||||
adjacent_difference_switch(_IIter, _IIter, _OIter, _BinaryOper, _Tag1, _Tag2, __gnu_parallel::parallelism);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper>
|
||||
_OIter
|
||||
adjacent_difference_switch(_IIter, _IIter, _OIter, _BinaryOper, random_access_iterator_tag, random_access_iterator_tag, __gnu_parallel::parallelism parallelism_tag);
|
||||
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename T, typename BinaryFunction1, typename BinaryFunction2>
|
||||
inline T
|
||||
inner_product(_IIter1, _IIter1, _IIter2, T, BinaryFunction1, BinaryFunction2, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename T>
|
||||
inline T
|
||||
inner_product(_IIter1, _IIter1, _IIter2, T, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename T, typename BinaryFunction1, typename BinaryFunction2>
|
||||
inline T
|
||||
inner_product(_IIter1, _IIter1, _IIter2, T, BinaryFunction1, BinaryFunction2, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename T>
|
||||
inline T
|
||||
inner_product(_IIter1, _IIter1, _IIter2, T, __gnu_parallel::parallelism parallelism_tag = __gnu_parallel::parallel_unbalanced);
|
||||
|
||||
template<typename _RAIter1, typename _RAIter2, typename T, typename BinaryFunction1, typename BinaryFunction2>
|
||||
T
|
||||
inner_product_switch(_RAIter1, _RAIter1, _RAIter2, T, BinaryFunction1, BinaryFunction2, random_access_iterator_tag, random_access_iterator_tag, __gnu_parallel::parallelism parallelism_tag);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename T, typename BinaryFunction1, typename BinaryFunction2, typename _Tag1, typename _Tag2>
|
||||
inline T
|
||||
inner_product_switch(_IIter1, _IIter1, _IIter2, T, BinaryFunction1, BinaryFunction2, _Tag1, _Tag2, __gnu_parallel::parallelism parallelism_tag);
|
||||
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
inline _OIter
|
||||
partial_sum(_IIter, _IIter, _OIter, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper>
|
||||
inline _OIter
|
||||
partial_sum(_IIter, _IIter, _OIter, _BinaryOper, __gnu_parallel::sequential_tag);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
inline _OIter
|
||||
partial_sum(_IIter, _IIter, _OIter result);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper>
|
||||
inline _OIter
|
||||
partial_sum(_IIter, _IIter, _OIter, _BinaryOper);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper, typename _Tag1, typename _Tag2>
|
||||
inline _OIter
|
||||
partial_sum_switch(_IIter, _IIter, _OIter, _BinaryOper, _Tag1, _Tag2);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryOper>
|
||||
_OIter
|
||||
partial_sum_switch(_IIter, _IIter, _OIter, _BinaryOper, random_access_iterator_tag, random_access_iterator_tag);
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
105
libstdc++-v3/include/parallel/omp_loop.h
Normal file
105
libstdc++-v3/include/parallel/omp_loop.h
Normal file
@ -0,0 +1,105 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/omp_loop.h
|
||||
* @brief Parallelization of embarrassingly parallel execution by
|
||||
* means of an OpenMP for loop.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_OMP_LOOP_H
|
||||
#define _GLIBCXX_PARALLEL_OMP_LOOP_H 1
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
#include <parallel/settings.h>
|
||||
#include <parallel/basic_iterator.h>
|
||||
|
||||
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 RandomAccessIterator, typename Op, typename Fu, typename Red, typename Result>
|
||||
Op
|
||||
for_each_template_random_access_omp_loop(RandomAccessIterator begin, RandomAccessIterator end, Op o, Fu& f, Red r, Result base, Result& output, typename std::iterator_traits<RandomAccessIterator>::difference_type bound)
|
||||
{
|
||||
typedef typename std::iterator_traits<RandomAccessIterator>::difference_type difference_type;
|
||||
|
||||
thread_index_t num_threads = (get_max_threads() < (end - begin)) ? get_max_threads() : static_cast<thread_index_t>((end - begin));
|
||||
Result *thread_results = new Result[num_threads];
|
||||
difference_type length = end - begin;
|
||||
|
||||
for (thread_index_t i = 0; i < num_threads; i++)
|
||||
{
|
||||
thread_results[i] = r(thread_results[i], f(o, begin+i));
|
||||
}
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
#pragma omp for schedule(dynamic, Settings::workstealing_chunk_size)
|
||||
for (difference_type pos = 0; pos < length; pos++)
|
||||
{
|
||||
thread_results[omp_get_thread_num()] = r(thread_results[omp_get_thread_num()], f(o, begin+pos));
|
||||
}
|
||||
}
|
||||
|
||||
for (thread_index_t i = 0; i < num_threads; i++)
|
||||
{
|
||||
output = r(output, thread_results[i]);
|
||||
}
|
||||
|
||||
delete [] thread_results;
|
||||
|
||||
// Points to last element processed (needed as return value for
|
||||
// some algorithms like transform).
|
||||
f.finish_iterator = begin + length;
|
||||
|
||||
return o;
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
#endif
|
111
libstdc++-v3/include/parallel/omp_loop_static.h
Normal file
111
libstdc++-v3/include/parallel/omp_loop_static.h
Normal file
@ -0,0 +1,111 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/omp_loop_static.h
|
||||
* @brief Parallelization of embarrassingly parallel execution by
|
||||
* means of an OpenMP for loop with static scheduling.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_OMP_LOOP_STATIC_H
|
||||
#define _GLIBCXX_PARALLEL_OMP_LOOP_STATIC_H 1
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
#include <parallel/settings.h>
|
||||
#include <parallel/basic_iterator.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
|
||||
/** @brief Embarrassingly parallel algorithm for random access
|
||||
* iterators, using an OpenMP for loop with static scheduling.
|
||||
*
|
||||
* @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 RandomAccessIterator, typename Op, typename Fu, typename Red, typename Result>
|
||||
Op
|
||||
for_each_template_random_access_omp_loop_static(RandomAccessIterator begin,
|
||||
RandomAccessIterator end,
|
||||
Op o, Fu& f, Red r,
|
||||
Result base, Result& output,
|
||||
typename std::iterator_traits<RandomAccessIterator>::difference_type bound)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
thread_index_t num_threads = (get_max_threads() < (end - begin)) ? get_max_threads() : (end - begin);
|
||||
Result *thread_results = new Result[num_threads];
|
||||
difference_type length = end - begin;
|
||||
|
||||
for (thread_index_t i = 0; i < num_threads; i++)
|
||||
{
|
||||
thread_results[i] = r(thread_results[i], f(o, begin+i));
|
||||
}
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
#pragma omp for schedule(static, Settings::workstealing_chunk_size)
|
||||
for (difference_type pos = 0; pos < length; pos++)
|
||||
{
|
||||
thread_results[omp_get_thread_num()] = r(thread_results[omp_get_thread_num()], f(o, begin+pos));
|
||||
}
|
||||
}
|
||||
|
||||
for (thread_index_t i = 0; i < num_threads; i++)
|
||||
{
|
||||
output = r(output, thread_results[i]);
|
||||
}
|
||||
|
||||
delete [] thread_results;
|
||||
|
||||
// Points to last element processed (needed as return value for
|
||||
// some algorithms like transform).
|
||||
f.finish_iterator = begin + length;
|
||||
|
||||
return o;
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
#endif
|
120
libstdc++-v3/include/parallel/par_loop.h
Normal file
120
libstdc++-v3/include/parallel/par_loop.h
Normal file
@ -0,0 +1,120 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/par_loop.h
|
||||
* @brief Parallelization of embarrassingly parallel execution by
|
||||
* means of equal splitting.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_PAR_LOOP_H
|
||||
#define _GLIBCXX_PARALLEL_PAR_LOOP_H 1
|
||||
|
||||
#include <omp.h>
|
||||
#include <parallel/settings.h>
|
||||
|
||||
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 RandomAccessIterator, typename Op, typename Fu, typename Red, typename Result>
|
||||
Op
|
||||
for_each_template_random_access_ed(RandomAccessIterator begin,
|
||||
RandomAccessIterator end, Op o, Fu& f,
|
||||
Red r, Result base, Result& output,
|
||||
typename std::iterator_traits<RandomAccessIterator>::difference_type bound)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
const difference_type length = end - begin;
|
||||
const difference_type settings_threads = static_cast<difference_type>(get_max_threads());
|
||||
const difference_type dmin = settings_threads < length ? settings_threads : length;
|
||||
const difference_type dmax = dmin > 1 ? dmin : 1;
|
||||
|
||||
thread_index_t num_threads = static_cast<thread_index_t>(dmax);
|
||||
|
||||
|
||||
Result *thread_results = new Result[num_threads];
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
// Neutral element.
|
||||
Result reduct = Result();
|
||||
|
||||
thread_index_t p = num_threads;
|
||||
thread_index_t iam = omp_get_thread_num();
|
||||
difference_type start = iam * length / p;
|
||||
difference_type limit = (iam == p - 1) ? length : (iam + 1) * length / p;
|
||||
|
||||
if (start < limit)
|
||||
{
|
||||
reduct = f(o, begin + start);
|
||||
start++;
|
||||
}
|
||||
|
||||
for (; start < limit; start++)
|
||||
reduct = r(reduct, f(o, begin + start));
|
||||
|
||||
thread_results[iam] = reduct;
|
||||
}
|
||||
|
||||
for (thread_index_t i = 0; i < num_threads; i++)
|
||||
output = r(output, thread_results[i]);
|
||||
|
||||
// Points to last element processed (needed as return value for
|
||||
// some algorithms like transform).
|
||||
f.finish_iterator = begin + length;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
#endif
|
48
libstdc++-v3/include/parallel/parallel.h
Normal file
48
libstdc++-v3/include/parallel/parallel.h
Normal file
@ -0,0 +1,48 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/parallel.h
|
||||
* @brief End-user include file. Provides advanced settings and
|
||||
* tuning options.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze and Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_PARALLEL_H
|
||||
#define _GLIBCXX_PARALLEL_PARALLEL_H 1
|
||||
|
||||
#include <parallel/features.h>
|
||||
#include <parallel/compiletime_settings.h>
|
||||
#include <parallel/types.h>
|
||||
#include <parallel/tags.h>
|
||||
#include <parallel/settings.h>
|
||||
|
||||
#endif
|
191
libstdc++-v3/include/parallel/partial_sum.h
Normal file
191
libstdc++-v3/include/parallel/partial_sum.h
Normal file
@ -0,0 +1,191 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/partial_sum.h
|
||||
* @brief Parallel implementation of std::partial_sum(), i. e. prefix
|
||||
* sums.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_PARTIAL_SUM_H
|
||||
#define _GLIBCXX_PARALLEL_PARTIAL_SUM_H 1
|
||||
|
||||
|
||||
#include <omp.h>
|
||||
#include <bits/stl_algobase.h>
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/numericfwd.h>
|
||||
|
||||
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 InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
inline OutputIterator
|
||||
parallel_partial_sum_basecase(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation bin_op,
|
||||
typename std::iterator_traits<InputIterator>::value_type value)
|
||||
{
|
||||
if (begin == end)
|
||||
return result;
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
value = bin_op(value, *begin);
|
||||
*result = value;
|
||||
result++;
|
||||
begin++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @brief Parallel partial sum implmenetation, 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 InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
OutputIterator
|
||||
parallel_partial_sum_linear(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation bin_op,
|
||||
typename std::iterator_traits<InputIterator>::difference_type n, int num_threads)
|
||||
{
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
if (num_threads > (n - 1))
|
||||
num_threads = static_cast<thread_index_t>(n - 1);
|
||||
if (num_threads < 2)
|
||||
{
|
||||
*result = *begin;
|
||||
return parallel_partial_sum_basecase(begin + 1, end, result + 1, bin_op, *begin);
|
||||
}
|
||||
|
||||
difference_type borders[num_threads + 2];
|
||||
|
||||
if (Settings::partial_sum_dilatation == 1.0f)
|
||||
equally_split(n, num_threads + 1, borders);
|
||||
else
|
||||
{
|
||||
difference_type chunk_length = (int)((double)n / ((double)num_threads + Settings::partial_sum_dilatation)), 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;
|
||||
}
|
||||
|
||||
value_type* sums = new value_type[num_threads];
|
||||
OutputIterator target_end;
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
int id = omp_get_thread_num();
|
||||
if (id == 0)
|
||||
{
|
||||
*result = *begin;
|
||||
parallel_partial_sum_basecase(begin + 1, begin + borders[1], result + 1, bin_op, *begin);
|
||||
sums[0] = *(result + borders[1] - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sums[id] = std::accumulate(begin + borders[id] + 1, begin + borders[id + 1], *(begin + borders[id]), bin_op, __gnu_parallel::sequential_tag());
|
||||
}
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
#pragma omp single
|
||||
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[id + 1], begin + borders[id + 2], result + borders[id + 1], bin_op, sums[id]);
|
||||
}
|
||||
|
||||
delete[] sums;
|
||||
|
||||
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 InputIterator, typename OutputIterator, typename BinaryOperation>
|
||||
OutputIterator
|
||||
parallel_partial_sum(InputIterator begin, InputIterator end,
|
||||
OutputIterator result, BinaryOperation bin_op)
|
||||
{
|
||||
_GLIBCXX_CALL(begin - end);
|
||||
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
difference_type n = end - begin;
|
||||
|
||||
int num_threads = get_max_threads();
|
||||
|
||||
switch (Settings::partial_sum_algorithm)
|
||||
{
|
||||
case Settings::LINEAR:
|
||||
// Need an initial offset.
|
||||
return parallel_partial_sum_linear(begin, end, result, bin_op,
|
||||
n, num_threads);
|
||||
default:
|
||||
// Partial_sum algorithm not implemented.
|
||||
_GLIBCXX_PARALLEL_ASSERT(0);
|
||||
return end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
389
libstdc++-v3/include/parallel/partition.h
Normal file
389
libstdc++-v3/include/parallel/partition.h
Normal file
@ -0,0 +1,389 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/partition.h
|
||||
* @brief Parallel implementation of std::partition(),
|
||||
* std::nth_element(), and std::partial_sort().
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler and Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_PARTITION_H
|
||||
#define _GLIBCXX_PARALLEL_PARTITION_H 1
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <parallel/sort.h>
|
||||
#include <bits/stl_algo.h>
|
||||
#include <parallel/parallel.h>
|
||||
|
||||
/** @brief Decide whether to declare certain variable volatile in this file. */
|
||||
#define _GLIBCXX_VOLATILE volatile
|
||||
|
||||
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 max_num_threads Maximum number of threads to use for this task.
|
||||
* @return Number of elements not fulfilling the predicate. */
|
||||
template<typename RandomAccessIterator, typename Predicate>
|
||||
inline typename std::iterator_traits<RandomAccessIterator>::difference_type
|
||||
parallel_partition(RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Predicate pred, thread_index_t max_num_threads)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
difference_type n = end - begin;
|
||||
|
||||
_GLIBCXX_CALL(n)
|
||||
|
||||
// Shared.
|
||||
_GLIBCXX_VOLATILE difference_type left = 0, right = n - 1;
|
||||
_GLIBCXX_VOLATILE difference_type leftover_left, leftover_right, leftnew, rightnew;
|
||||
bool* reserved_left, * reserved_right;
|
||||
|
||||
reserved_left = new bool[max_num_threads];
|
||||
reserved_right = new bool[max_num_threads];
|
||||
|
||||
difference_type chunk_size;
|
||||
if (Settings::partition_chunk_share > 0.0)
|
||||
chunk_size = std::max((difference_type)Settings::partition_chunk_size, (difference_type)((double)n * Settings::partition_chunk_share / (double)max_num_threads));
|
||||
else
|
||||
chunk_size = Settings::partition_chunk_size;
|
||||
|
||||
// At least good for two processors.
|
||||
while (right - left + 1 >= 2 * max_num_threads * chunk_size)
|
||||
{
|
||||
difference_type num_chunks = (right - left + 1) / chunk_size;
|
||||
thread_index_t num_threads = (int)std::min((difference_type)max_num_threads, num_chunks / 2);
|
||||
|
||||
for (int r = 0; r < num_threads; r++)
|
||||
{
|
||||
reserved_left[r] = false;
|
||||
reserved_right[r] = false;
|
||||
}
|
||||
leftover_left = 0;
|
||||
leftover_right = 0;
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
// Private.
|
||||
difference_type thread_left, thread_left_border, thread_right, thread_right_border;
|
||||
thread_left = left + 1;
|
||||
|
||||
// Just to satify 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)
|
||||
#pragma omp critical
|
||||
{
|
||||
if (left + (chunk_size - 1) > right)
|
||||
iam_finished = true;
|
||||
else
|
||||
{
|
||||
thread_left = left;
|
||||
thread_left_border = left + (chunk_size - 1);
|
||||
left += chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (thread_right < thread_right_border)
|
||||
#pragma omp critical
|
||||
{
|
||||
if (left > right - (chunk_size - 1))
|
||||
iam_finished = true;
|
||||
else
|
||||
{
|
||||
thread_right = right;
|
||||
thread_right_border = right - (chunk_size - 1);
|
||||
right -= chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
difference_type swapstart = -1;
|
||||
#pragma omp critical
|
||||
{
|
||||
for (int r = 0; r < leftover_left; r++)
|
||||
if (!reserved_left[r])
|
||||
{
|
||||
reserved_left[r] = true;
|
||||
swapstart = left - (r + 1) * chunk_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_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
|
||||
difference_type swapstart = -1;
|
||||
#pragma omp critical
|
||||
{
|
||||
for (int r = 0; r < leftover_right; r++)
|
||||
if (!reserved_right[r])
|
||||
{
|
||||
reserved_right[r] = true;
|
||||
swapstart = right + r * chunk_size + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
_GLIBCXX_PARALLEL_ASSERT(swapstart != -1);
|
||||
#endif
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
#pragma omp barrier
|
||||
#endif
|
||||
|
||||
#pragma omp barrier
|
||||
left = leftnew;
|
||||
right = rightnew;
|
||||
}
|
||||
} // end "recursion"
|
||||
|
||||
difference_type 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;
|
||||
|
||||
// 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 RandomAccessIterator, typename Comparator>
|
||||
void
|
||||
parallel_nth_element(RandomAccessIterator begin, RandomAccessIterator nth, RandomAccessIterator end, Comparator comp)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
_GLIBCXX_CALL(end - begin)
|
||||
|
||||
RandomAccessIterator split;
|
||||
value_type pivot;
|
||||
random_number rng;
|
||||
|
||||
difference_type minimum_length = std::max<difference_type>(2, Settings::partition_minimal_n);
|
||||
|
||||
// Break if input range to small.
|
||||
while (static_cast<sequence_index_t>(end - begin) >= minimum_length)
|
||||
{
|
||||
difference_type n = end - begin;
|
||||
|
||||
RandomAccessIterator 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;
|
||||
|
||||
// XXX Comparator must have first_value_type, second_value_type, result_type
|
||||
// Comparator == __gnu_parallel::lexicographic<S, int, __gnu_parallel::less<S, S> >
|
||||
// pivot_pos == std::pair<S, int>*
|
||||
// XXX binder2nd only for RandomAccessIterators??
|
||||
__gnu_parallel::binder2nd<Comparator, value_type, value_type, bool> pred(comp, *pivot_pos);
|
||||
|
||||
// Divide, leave pivot unchanged in last place.
|
||||
RandomAccessIterator 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 stricly larger than the pivot.
|
||||
__gnu_parallel::unary_negate<__gnu_parallel::binder1st<Comparator, value_type, value_type, bool>, value_type> pred(__gnu_parallel::binder1st<Comparator, value_type, value_type, 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 RandomAccessIterator, typename Comparator>
|
||||
void
|
||||
parallel_partial_sort(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end, Comparator comp)
|
||||
{
|
||||
parallel_nth_element(begin, middle, end, comp);
|
||||
std::sort(begin, middle, comp);
|
||||
}
|
||||
|
||||
} //namespace __gnu_parallel
|
||||
|
||||
#undef _GLIBCXX_VOLATILE
|
||||
|
||||
#endif
|
153
libstdc++-v3/include/parallel/queue.h
Normal file
153
libstdc++-v3/include/parallel/queue.h
Normal file
@ -0,0 +1,153 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/queue.h
|
||||
* @brief Lock-free double-ended queue.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_QUEUE_H
|
||||
#define _GLIBCXX_PARALLEL_QUEUE_H 1
|
||||
|
||||
#include <parallel/types.h>
|
||||
#include <parallel/base.h>
|
||||
#include <parallel/compatibility.h>
|
||||
|
||||
/** @brief Decide whether to declare certain variable volatile in this file. */
|
||||
#define _GLIBCXX_VOLATILE volatile
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/**@brief Double-ended queue of bounded size, allowing lock-free
|
||||
* 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.
|
||||
* Calling them would not make sense in a concurrent setting.
|
||||
* @param T Contained element type. */
|
||||
template<typename T>
|
||||
class RestrictedBoundedConcurrentQueue
|
||||
{
|
||||
private:
|
||||
/** @brief Array of elements, seen as cyclic buffer. */
|
||||
T* base;
|
||||
|
||||
/** @brief Maximal number of elements contained at the same time. */
|
||||
sequence_index_t max_size;
|
||||
|
||||
/** @brief Cyclic begin and end pointers contained in one
|
||||
atomically changeable value. */
|
||||
_GLIBCXX_VOLATILE lcas_t borders;
|
||||
|
||||
public:
|
||||
/** @brief Constructor. Not to be called concurrent, of course.
|
||||
* @param max_size Maximal number of elements to be contained. */
|
||||
RestrictedBoundedConcurrentQueue(sequence_index_t max_size)
|
||||
{
|
||||
this->max_size = max_size;
|
||||
base = new T[max_size];
|
||||
borders = encode2(0, 0);
|
||||
#pragma omp flush
|
||||
}
|
||||
|
||||
/** @brief Destructor. Not to be called concurrent, of course. */
|
||||
~RestrictedBoundedConcurrentQueue()
|
||||
{
|
||||
delete[] base;
|
||||
}
|
||||
|
||||
/** @brief Pushes one element into the queue at the front end.
|
||||
* Must not be called concurrently with pop_front(). */
|
||||
void push_front(const T& t)
|
||||
{
|
||||
lcas_t former_borders = borders;
|
||||
int former_front, former_back;
|
||||
decode2(former_borders, former_front, former_back);
|
||||
*(base + former_front % max_size) = t;
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
// Otherwise: front - back > max_size eventually.
|
||||
_GLIBCXX_PARALLEL_ASSERT(((former_front + 1) - former_back) <= max_size);
|
||||
#endif
|
||||
fetch_and_add(&borders, encode2(1, 0));
|
||||
}
|
||||
|
||||
/** @brief Pops one element from the queue at the front end.
|
||||
* Must not be called concurrently with pop_front(). */
|
||||
bool pop_front(T& t)
|
||||
{
|
||||
int former_front, former_back;
|
||||
#pragma omp flush
|
||||
decode2(borders, former_front, former_back);
|
||||
while (former_front > former_back)
|
||||
{
|
||||
// Chance.
|
||||
lcas_t former_borders = encode2(former_front, former_back);
|
||||
lcas_t new_borders = encode2(former_front - 1, former_back);
|
||||
if (compare_and_swap(&borders, former_borders, new_borders))
|
||||
{
|
||||
t = *(base + (former_front - 1) % max_size);
|
||||
return true;
|
||||
}
|
||||
#pragma omp flush
|
||||
decode2(borders, former_front, former_back);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @brief Pops one element from the queue at the front end.
|
||||
* Must not be called concurrently with pop_front(). */
|
||||
bool pop_back(T& t) //queue behavior
|
||||
{
|
||||
int former_front, former_back;
|
||||
#pragma omp flush
|
||||
decode2(borders, former_front, former_back);
|
||||
while (former_front > former_back)
|
||||
{
|
||||
// Chance.
|
||||
lcas_t former_borders = encode2(former_front, former_back);
|
||||
lcas_t new_borders = encode2(former_front, former_back + 1);
|
||||
if (compare_and_swap(&borders, former_borders, new_borders))
|
||||
{
|
||||
t = *(base + former_back % max_size);
|
||||
return true;
|
||||
}
|
||||
#pragma omp flush
|
||||
decode2(borders, former_front, former_back);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} //namespace __gnu_parallel
|
||||
|
||||
#undef _GLIBCXX_VOLATILE
|
||||
|
||||
#endif
|
172
libstdc++-v3/include/parallel/quicksort.h
Normal file
172
libstdc++-v3/include/parallel/quicksort.h
Normal file
@ -0,0 +1,172 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/quicksort.h
|
||||
* @brief Implementation of a unbalanced parallel quicksort (in-place).
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_QUICKSORT_H
|
||||
#define _GLIBCXX_PARALLEL_QUICKSORT_H 1
|
||||
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/partition.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/** @brief Unbalanced quicksort divide step.
|
||||
* @param begin Begin iterator of subsequence.
|
||||
* @param end End iterator of subsequence.
|
||||
* @param comp Comparator.
|
||||
* @param pivot_rank Desired rank of the pivot.
|
||||
* @param num_samples Chosse pivot from that many samples.
|
||||
* @param num_threads Number of threads that are allowed to work on
|
||||
* this part.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename Comparator>
|
||||
inline typename std::iterator_traits<RandomAccessIterator>::difference_type
|
||||
parallel_sort_qs_divide(RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Comparator comp,
|
||||
typename std::iterator_traits<RandomAccessIterator>::difference_type pivot_rank,
|
||||
typename std::iterator_traits<RandomAccessIterator>::difference_type num_samples, thread_index_t num_threads)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
difference_type n = end - begin;
|
||||
num_samples = std::min(num_samples, n);
|
||||
value_type samples[num_samples];
|
||||
|
||||
for (difference_type s = 0; s < num_samples; s++)
|
||||
samples[s] = begin[(unsigned long long)s * n / num_samples];
|
||||
|
||||
__gnu_sequential::sort(samples, samples + num_samples, comp);
|
||||
|
||||
value_type& pivot = samples[pivot_rank * num_samples / n];
|
||||
|
||||
__gnu_parallel::binder2nd<Comparator, value_type, value_type, bool> pred(comp, pivot);
|
||||
difference_type split = parallel_partition(begin, end, pred, num_threads);
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
/** @brief Unbalanced quicksort conquer 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.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
parallel_sort_qs_conquer(RandomAccessIterator begin, RandomAccessIterator end, Comparator comp, int num_threads)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
if (num_threads <= 1)
|
||||
{
|
||||
__gnu_sequential::sort(begin, end, comp);
|
||||
return;
|
||||
}
|
||||
|
||||
difference_type n = end - begin, pivot_rank;
|
||||
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
thread_index_t num_processors_left;
|
||||
|
||||
if ((num_threads % 2) == 1)
|
||||
num_processors_left = num_threads / 2 + 1;
|
||||
else
|
||||
num_processors_left = num_threads / 2;
|
||||
|
||||
pivot_rank = n * num_processors_left / num_threads;
|
||||
|
||||
difference_type split = parallel_sort_qs_divide(begin, end, comp, pivot_rank,
|
||||
Settings::sort_qs_num_samples_preset, num_threads);
|
||||
|
||||
#pragma omp parallel sections
|
||||
{
|
||||
#pragma omp section
|
||||
parallel_sort_qs_conquer(begin, begin + split, comp, num_processors_left);
|
||||
#pragma omp section
|
||||
parallel_sort_qs_conquer(begin + split, end, comp, num_threads - num_processors_left);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** @brief Unbalanced quicksort main call.
|
||||
* @param begin Begin iterator of input sequence.
|
||||
* @param end End iterator input sequence, ignored.
|
||||
* @param comp Comparator.
|
||||
* @param n Length of input sequence.
|
||||
* @param num_threads Number of threads that are allowed to work on
|
||||
* this part.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
parallel_sort_qs(RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Comparator comp,
|
||||
typename std::iterator_traits<RandomAccessIterator>::difference_type n, int num_threads)
|
||||
{
|
||||
_GLIBCXX_CALL(n)
|
||||
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
// At least one element per processor.
|
||||
if (num_threads > n)
|
||||
num_threads = static_cast<thread_index_t>(n);
|
||||
|
||||
Settings::sort_qs_num_samples_preset = 100;
|
||||
|
||||
// Hard to avoid.
|
||||
omp_set_num_threads(num_threads);
|
||||
|
||||
bool old_nested = (omp_get_nested() != 0);
|
||||
omp_set_nested(true);
|
||||
parallel_sort_qs_conquer(begin, begin + n, comp, num_threads);
|
||||
omp_set_nested(old_nested);
|
||||
}
|
||||
|
||||
} //namespace __gnu_parallel
|
||||
|
||||
#endif
|
386
libstdc++-v3/include/parallel/random_number.h
Normal file
386
libstdc++-v3/include/parallel/random_number.h
Normal file
@ -0,0 +1,386 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/random_number.h
|
||||
* @brief Random number generator based on the Mersenne twister.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_RANDOM_NUMBER_H
|
||||
#define _GLIBCXX_PARALLEL_RANDOM_NUMBER_H 1
|
||||
|
||||
#include <parallel/types.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
// XXX use tr1 random number.
|
||||
// http://www.math.keio.ac.jp/matumoto/emt.html
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
class mersenne_twister
|
||||
{
|
||||
public:
|
||||
typedef UIntType result_type;
|
||||
static const int word_size = w;
|
||||
static const int state_size = n;
|
||||
static const int shift_size = m;
|
||||
static const int mask_bits = r;
|
||||
static const UIntType parameter_a = a;
|
||||
static const int output_u = u;
|
||||
static const int output_s = s;
|
||||
static const UIntType output_b = b;
|
||||
static const int output_t = t;
|
||||
static const UIntType output_c = c;
|
||||
static const int output_l = l;
|
||||
|
||||
static const bool has_fixed_range = false;
|
||||
|
||||
mersenne_twister() { seed(); }
|
||||
|
||||
#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520)
|
||||
// Work around overload resolution problem (Gennadiy E. Rozental)
|
||||
explicit mersenne_twister(const UIntType& value)
|
||||
#else
|
||||
explicit mersenne_twister(UIntType value)
|
||||
#endif
|
||||
{ seed(value); }
|
||||
template<typename It> mersenne_twister(It& first, It last) { seed(first,last); }
|
||||
|
||||
template<typename Generator>
|
||||
explicit mersenne_twister(Generator & gen) { seed(gen); }
|
||||
|
||||
// compiler-generated copy ctor and assignment operator are fine
|
||||
|
||||
void seed() { seed(UIntType(5489)); }
|
||||
|
||||
#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520)
|
||||
// Work around overload resolution problem (Gennadiy E. Rozental)
|
||||
void seed(const UIntType& value)
|
||||
#else
|
||||
void seed(UIntType value)
|
||||
#endif
|
||||
{
|
||||
// New seeding algorithm from
|
||||
// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
|
||||
// In the previous versions, MSBs of the seed affected only MSBs of the
|
||||
// state x[].
|
||||
const UIntType mask = ~0u;
|
||||
x[0] = value & mask;
|
||||
for (i = 1; i < n; i++) {
|
||||
// See Knuth "The Art of Computer Programming" Vol. 2, 3rd ed., page 106
|
||||
x[i] = (1812433253UL * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask;
|
||||
}
|
||||
}
|
||||
|
||||
// For GCC, moving this function out-of-line prevents inlining, which may
|
||||
// reduce overall object code size. However, MSVC does not grok
|
||||
// out-of-line definitions of member function templates.
|
||||
template<typename Generator>
|
||||
void seed(Generator & gen)
|
||||
{
|
||||
// I could have used std::generate_n, but it takes "gen" by value
|
||||
for (int j = 0; j < n; j++)
|
||||
x[j] = gen();
|
||||
i = n;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
void seed(It& first, It last)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < n && first != last; ++j, ++first)
|
||||
x[j] = *first;
|
||||
i = n;
|
||||
/* if (first == last && j < n)
|
||||
throw std::invalid_argument("mersenne_twister::seed");*/
|
||||
}
|
||||
|
||||
result_type min() const { return 0; }
|
||||
result_type max() const
|
||||
{
|
||||
// avoid "left shift count >= with of type" warning
|
||||
result_type res = 0;
|
||||
for (int i = 0; i < w; ++i)
|
||||
res |= (1u << i);
|
||||
return res;
|
||||
}
|
||||
|
||||
result_type operator()();
|
||||
static bool validation(result_type v) { return val == v; }
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
friend bool operator==(const mersenne_twister& x, const mersenne_twister& y)
|
||||
{
|
||||
for (int j = 0; j < state_size; ++j)
|
||||
if (x.compute(j) != y.compute(j))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
friend bool operator!=(const mersenne_twister& x, const mersenne_twister& y)
|
||||
{ return !(x == y); }
|
||||
#else
|
||||
// Use a member function; Streamable concept not supported.
|
||||
bool operator==(const mersenne_twister& rhs) const
|
||||
{
|
||||
for (int j = 0; j < state_size; ++j)
|
||||
if (compute(j) != rhs.compute(j))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const mersenne_twister& rhs) const
|
||||
{ return !(*this == rhs); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
// returns x(i-n+index), where index is in 0..n-1
|
||||
UIntType compute(unsigned int index) const
|
||||
{
|
||||
// equivalent to (i-n+index) % 2n, but doesn't produce negative numbers
|
||||
return x[ (i + n + index) % (2*n) ];
|
||||
}
|
||||
void twist(int block);
|
||||
|
||||
// state representation: next output is o(x(i))
|
||||
// x[0] ... x[k] x[k+1] ... x[n-1] x[n] ... x[2*n-1] represents
|
||||
// x(i-k) ... x(i) x(i+1) ... x(i-k+n-1) x(i-k-n) ... x[i(i-k-1)]
|
||||
// The goal is to always have x(i-n) ... x(i-1) available for
|
||||
// operator== and save/restore.
|
||||
|
||||
UIntType x[2*n];
|
||||
int i;
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
||||
// A definition is required even for integral static constants
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const bool mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::has_fixed_range;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::state_size;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::shift_size;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::mask_bits;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::parameter_a;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_u;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_s;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_b;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_t;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_c;
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_l;
|
||||
#endif
|
||||
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
void mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::twist(int block)
|
||||
{
|
||||
const UIntType upper_mask = (~0u) << r;
|
||||
const UIntType lower_mask = ~upper_mask;
|
||||
|
||||
if (block == 0) {
|
||||
for (int j = n; j < 2*n; j++) {
|
||||
UIntType y = (x[j-n] & upper_mask) | (x[j-(n-1)] & lower_mask);
|
||||
x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
|
||||
}
|
||||
} else if (block == 1) {
|
||||
// split loop to avoid costly modulo operations
|
||||
{ // extra scope for MSVC brokenness w.r.t. for scope
|
||||
for (int j = 0; j < n-m; j++) {
|
||||
UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
|
||||
x[j] = x[j+n+m] ^ (y >> 1) ^ (y&1 ? a : 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = n-m; j < n-1; j++) {
|
||||
UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
|
||||
x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
|
||||
}
|
||||
// last iteration
|
||||
UIntType y = (x[2*n-1] & upper_mask) | (x[0] & lower_mask);
|
||||
x[n-1] = x[m-1] ^ (y >> 1) ^ (y&1 ? a : 0);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename UIntType, int w, int n, int m, int r, UIntType a, int u,
|
||||
int s, UIntType b, int t, UIntType c, int l, UIntType val>
|
||||
inline typename mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::result_type
|
||||
mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::operator()()
|
||||
{
|
||||
if (i == n)
|
||||
twist(0);
|
||||
else if (i >= 2*n)
|
||||
twist(1);
|
||||
// Step 4
|
||||
UIntType z = x[i];
|
||||
++i;
|
||||
z ^= (z >> u);
|
||||
z ^= ((z << s) & b);
|
||||
z ^= ((z << t) & c);
|
||||
z ^= (z >> l);
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
typedef mersenne_twister<uint32,32,351,175,19,0xccab8ee7,11,
|
||||
7,0x31b6ab00,15,0xffe50000,17, 0xa37d3c92> mt11213b;
|
||||
|
||||
// validation by experiment from mt19937.c
|
||||
typedef mersenne_twister<uint32,32,624,397,31,0x9908b0df,11,
|
||||
7,0x9d2c5680,15,0xefc60000,18, 3346425566U> mt19937;
|
||||
|
||||
/** @brief Random number generator, based on the Mersenne twister. */
|
||||
class random_number
|
||||
{
|
||||
private:
|
||||
mt19937 mt;
|
||||
uint64 supremum, RAND_SUP;
|
||||
double supremum_reciprocal, RAND_SUP_REC;
|
||||
|
||||
uint64 cache; /* assumed to be twice as long as the usual random number */
|
||||
int bits_left; /* bit results */
|
||||
|
||||
static inline uint32 scale_down(uint64 x,
|
||||
#if _GLIBCXX_SCALE_DOWN_FPU
|
||||
uint64 /*supremum*/, double supremum_reciprocal)
|
||||
#else
|
||||
uint64 supremum, double /*supremum_reciprocal*/)
|
||||
#endif
|
||||
{
|
||||
#if _GLIBCXX_SCALE_DOWN_FPU
|
||||
return (uint32)(x * supremum_reciprocal);
|
||||
#else
|
||||
return static_cast<uint32>(x % supremum);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
/** @brief Default constructor. Seed with 0. */
|
||||
random_number() :
|
||||
mt(0),
|
||||
supremum(0x100000000ULL),
|
||||
RAND_SUP(1ULL << (sizeof(uint32) * 8)),
|
||||
supremum_reciprocal((double)supremum / (double)RAND_SUP),
|
||||
RAND_SUP_REC(1.0 / (double)RAND_SUP),
|
||||
cache(0), bits_left(0)
|
||||
{
|
||||
}
|
||||
|
||||
/** @brief Constructor.
|
||||
* @param seed Random seed.
|
||||
* @param supremum Generate integer random numbers in the interval @c [0,supremum). */
|
||||
random_number(uint32 seed, uint64 supremum = 0x100000000ULL) :
|
||||
mt(seed),
|
||||
supremum(supremum),
|
||||
RAND_SUP(1ULL << (sizeof(uint32) * 8)),
|
||||
supremum_reciprocal((double)supremum / (double)RAND_SUP),
|
||||
RAND_SUP_REC(1.0 / (double)RAND_SUP),
|
||||
cache(0), bits_left(0)
|
||||
{
|
||||
}
|
||||
|
||||
/** @brief Generate unsigned random 32-bit integer. */
|
||||
inline uint32 operator()()
|
||||
{
|
||||
return scale_down(mt(), supremum, supremum_reciprocal);
|
||||
}
|
||||
|
||||
/** @brief Generate unsigned random 32-bit integer in the interval @c [0,local_supremum). */
|
||||
inline uint32 operator()(uint64 local_supremum)
|
||||
{
|
||||
return scale_down(mt(), local_supremum, (double)local_supremum * RAND_SUP_REC);
|
||||
}
|
||||
|
||||
/** @brief Set the random seed.
|
||||
* @param seed to set. */
|
||||
inline void set_seed(uint32 seed)
|
||||
{
|
||||
mt.seed(seed);
|
||||
cache = mt();
|
||||
bits_left = 32;
|
||||
}
|
||||
|
||||
/** @brief Generate a number of random bits, compile-time parameter. */
|
||||
template<int bits>
|
||||
inline unsigned long genrand_bits()
|
||||
{
|
||||
unsigned long res = cache & ((1 << bits) - 1);
|
||||
cache = cache >> bits;
|
||||
bits_left -= bits;
|
||||
if (bits_left < 32)
|
||||
{
|
||||
cache |= (((uint64)mt()) << bits_left);
|
||||
bits_left += 32;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** @brief Generate a number of random bits, run-time parameter.
|
||||
* @param bits Number of bits to generate. */
|
||||
inline unsigned long genrand_bits(int bits)
|
||||
{
|
||||
unsigned long res = cache & ((1 << bits) - 1);
|
||||
cache = cache >> bits;
|
||||
bits_left -= bits;
|
||||
if (bits_left < 32)
|
||||
{
|
||||
cache |= (((uint64)mt()) << bits_left);
|
||||
bits_left += 32;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace __gnu_parallel
|
||||
|
||||
#endif
|
516
libstdc++-v3/include/parallel/random_shuffle.h
Normal file
516
libstdc++-v3/include/parallel/random_shuffle.h
Normal file
@ -0,0 +1,516 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/random_shuffle.h
|
||||
* @brief Parallel implementation of std::random_shuffle().
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_RANDOM_SHUFFLE_H
|
||||
#define _GLIBCXX_PARALLEL_RANDOM_SHUFFLE_H 1
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <bits/stl_algo.h>
|
||||
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/base.h>
|
||||
#include <parallel/random_number.h>
|
||||
#include <parallel/timing.h>
|
||||
|
||||
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 bin_index;
|
||||
|
||||
/** @brief Data known to every thread participating in
|
||||
__gnu_parallel::parallel_random_shuffle(). */
|
||||
template<typename RandomAccessIterator>
|
||||
struct DRandomShufflingGlobalData
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
/** @brief Begin iterator of the source. */
|
||||
RandomAccessIterator& source;
|
||||
|
||||
/** @brief Temporary arrays for each thread. */
|
||||
value_type** temporaries;
|
||||
|
||||
/** @brief Two-dimensional array to hold the thread-bin distribution.
|
||||
*
|
||||
* Dimensions (num_threads + 1) x (num_bins + 1). */
|
||||
difference_type** dist;
|
||||
|
||||
/** @brief Start indexes of the threads' chunks. */
|
||||
difference_type* starts;
|
||||
|
||||
/** @brief Number of the thread that will further process the
|
||||
corresponding bin. */
|
||||
thread_index_t* bin_proc;
|
||||
|
||||
/** @brief Number of bins to distribute to. */
|
||||
int num_bins;
|
||||
|
||||
/** @brief Number of bits needed to address the bins. */
|
||||
int num_bits;
|
||||
|
||||
/** @brief Constructor. */
|
||||
DRandomShufflingGlobalData(RandomAccessIterator& _source)
|
||||
: source(_source) { }
|
||||
};
|
||||
|
||||
/** @brief Local data for a thread participating in
|
||||
__gnu_parallel::parallel_random_shuffle().
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename RandomNumberGenerator>
|
||||
struct DRSSorterPU
|
||||
{
|
||||
/** @brief Number of threads participating in total. */
|
||||
int num_threads;
|
||||
|
||||
/** @brief Number of owning thread. */
|
||||
int iam;
|
||||
|
||||
/** @brief Begin index for bins taken care of by this thread. */
|
||||
bin_index bins_begin;
|
||||
|
||||
/** @brief End index for bins taken care of by this thread. */
|
||||
bin_index bins_end;
|
||||
|
||||
/** @brief Random seed for this thread. */
|
||||
uint32 seed;
|
||||
|
||||
/** @brief Pointer to global data. */
|
||||
DRandomShufflingGlobalData<RandomAccessIterator>* 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 Arary of thread-local data records. */
|
||||
template<typename RandomAccessIterator, typename RandomNumberGenerator>
|
||||
inline void parallel_random_shuffle_drs_pu(DRSSorterPU<RandomAccessIterator, RandomNumberGenerator>* pus)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
Timing<sequential_tag> t;
|
||||
t.tic();
|
||||
|
||||
DRSSorterPU<RandomAccessIterator, RandomNumberGenerator>* d = &pus[omp_get_thread_num()];
|
||||
DRandomShufflingGlobalData<RandomAccessIterator>* sd = d->sd;
|
||||
thread_index_t iam = d->iam;
|
||||
|
||||
// Indexing: dist[bin][processor]
|
||||
difference_type length = sd->starts[iam + 1] - sd->starts[iam];
|
||||
bin_index* oracles = new bin_index[length];
|
||||
difference_type* dist = new difference_type[sd->num_bins + 1];
|
||||
bin_index* bin_proc = new bin_index[sd->num_bins];
|
||||
value_type** temporaries = new value_type*[d->num_threads];
|
||||
|
||||
// Compute oracles and count appearances.
|
||||
for (bin_index b = 0; b < sd->num_bins + 1; b++)
|
||||
dist[b] = 0;
|
||||
int num_bits = sd->num_bits;
|
||||
|
||||
random_number rng(d->seed);
|
||||
|
||||
// First main loop.
|
||||
for (difference_type i = 0; i < length; i++)
|
||||
{
|
||||
bin_index oracle = random_number_pow2(num_bits, rng);
|
||||
oracles[i] = oracle;
|
||||
|
||||
// To allow prefix (partial) sum.
|
||||
dist[oracle + 1]++;
|
||||
}
|
||||
|
||||
for (bin_index b = 0; b < sd->num_bins + 1; b++)
|
||||
sd->dist[b][iam + 1] = dist[b];
|
||||
|
||||
t.tic();
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic();
|
||||
|
||||
#pragma omp single
|
||||
{
|
||||
// Sum up bins, sd->dist[s + 1][d->num_threads] now contains the
|
||||
// total number of items in bin s
|
||||
for (bin_index s = 0; s < sd->num_bins; s++)
|
||||
partial_sum(sd->dist[s + 1], sd->dist[s + 1] + d->num_threads + 1, sd->dist[s + 1]);
|
||||
}
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic();
|
||||
|
||||
sequence_index_t offset = 0, global_offset = 0;
|
||||
for (bin_index s = 0; s < d->bins_begin; s++)
|
||||
global_offset += sd->dist[s + 1][d->num_threads];
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
for (bin_index s = d->bins_begin; s < d->bins_end; s++)
|
||||
{
|
||||
for (int t = 0; t < d->num_threads + 1; t++)
|
||||
sd->dist[s + 1][t] += offset;
|
||||
offset = sd->dist[s + 1][d->num_threads];
|
||||
}
|
||||
|
||||
sd->temporaries[iam] = new value_type[offset];
|
||||
|
||||
t.tic();
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic();
|
||||
|
||||
// Draw local copies to avoid false sharing.
|
||||
for (bin_index b = 0; b < sd->num_bins + 1; b++)
|
||||
dist[b] = sd->dist[b][iam];
|
||||
for (bin_index b = 0; b < sd->num_bins; b++)
|
||||
bin_proc[b] = sd->bin_proc[b];
|
||||
for (thread_index_t t = 0; t < d->num_threads; t++)
|
||||
temporaries[t] = sd->temporaries[t];
|
||||
|
||||
RandomAccessIterator source = sd->source;
|
||||
difference_type start = sd->starts[iam];
|
||||
|
||||
// Distribute according to oracles, second main loop.
|
||||
for (difference_type i = 0; i < length; i++)
|
||||
{
|
||||
bin_index target_bin = oracles[i];
|
||||
thread_index_t target_p = bin_proc[target_bin];
|
||||
|
||||
// Last column [d->num_threads] stays unchanged.
|
||||
temporaries[target_p][dist[target_bin + 1]++] = *(source + i + start);
|
||||
}
|
||||
|
||||
delete[] oracles;
|
||||
delete[] dist;
|
||||
delete[] bin_proc;
|
||||
delete[] temporaries;
|
||||
|
||||
t.tic();
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic();
|
||||
|
||||
// Shuffle bins internally.
|
||||
for (bin_index b = d->bins_begin; b < d->bins_end; b++)
|
||||
{
|
||||
value_type* begin = sd->temporaries[iam] + ((b == d->bins_begin) ? 0 : sd->dist[b][d->num_threads]),
|
||||
* end = sd->temporaries[iam] + sd->dist[b + 1][d->num_threads];
|
||||
sequential_random_shuffle(begin, end, rng);
|
||||
std::copy(begin, end, sd->source + global_offset + ((b == d->bins_begin) ? 0 : sd->dist[b][d->num_threads]));
|
||||
}
|
||||
|
||||
delete[] sd->temporaries[iam];
|
||||
|
||||
t.tic();
|
||||
|
||||
t.print();
|
||||
}
|
||||
|
||||
/** @brief Round up to the next greater power of 2.
|
||||
* @param x Integer to round up */
|
||||
template<typename T>
|
||||
T round_up_to_pow2(T x)
|
||||
{
|
||||
if (x <= 1)
|
||||
return 1;
|
||||
else
|
||||
return (T)1 << (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 RandomAccessIterator, typename RandomNumberGenerator>
|
||||
inline void
|
||||
parallel_random_shuffle_drs(RandomAccessIterator begin, RandomAccessIterator end, typename std::iterator_traits<RandomAccessIterator>::difference_type n, int num_threads, RandomNumberGenerator& rng)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
_GLIBCXX_CALL(n)
|
||||
|
||||
if (num_threads > n)
|
||||
num_threads = static_cast<thread_index_t>(n);
|
||||
|
||||
bin_index 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((difference_type)1, (difference_type)(n / (Settings::L1_cache_size_lb / sizeof(value_type))));
|
||||
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, (difference_type)num_bins_cache);
|
||||
|
||||
#if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB
|
||||
// 2 TLB entries needed per bin.
|
||||
num_bins = std::min((difference_type)Settings::TLB_size / 2, num_bins);
|
||||
#endif
|
||||
num_bins = round_up_to_pow2(num_bins);
|
||||
|
||||
if (num_bins < num_bins_cache)
|
||||
{
|
||||
#endif
|
||||
// Now try the L2 cache
|
||||
// Must fit into L2
|
||||
num_bins_cache = static_cast<bin_index>(std::max((difference_type)1, (difference_type)(n / (Settings::L2_cache_size / sizeof(value_type)))));
|
||||
num_bins_cache = round_up_to_pow2(num_bins_cache);
|
||||
|
||||
// No more buckets than TLB entries, power of 2.
|
||||
num_bins = static_cast<bin_index>(std::min(n, (difference_type)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.
|
||||
num_bins = std::min((difference_type)Settings::TLB_size / 2, num_bins);
|
||||
#endif
|
||||
num_bins = round_up_to_pow2(num_bins);
|
||||
#if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1
|
||||
}
|
||||
#endif
|
||||
|
||||
num_threads = std::min((bin_index)num_threads, (bin_index)num_bins);
|
||||
|
||||
if (num_threads <= 1)
|
||||
return sequential_random_shuffle(begin, end, rng);
|
||||
|
||||
DRandomShufflingGlobalData<RandomAccessIterator> sd(begin);
|
||||
|
||||
DRSSorterPU<RandomAccessIterator, random_number >* pus = new DRSSorterPU<RandomAccessIterator, random_number >[num_threads];
|
||||
|
||||
sd.temporaries = new value_type*[num_threads];
|
||||
//sd.oracles = new bin_index[n];
|
||||
sd.dist = new difference_type*[num_bins + 1];
|
||||
sd.bin_proc = new thread_index_t[num_bins];
|
||||
for (bin_index b = 0; b < num_bins + 1; b++)
|
||||
sd.dist[b] = new difference_type[num_threads + 1];
|
||||
for (bin_index b = 0; b < (num_bins + 1); b++)
|
||||
{
|
||||
sd.dist[0][0] = 0;
|
||||
sd.dist[b][0] = 0;
|
||||
}
|
||||
difference_type* starts = sd.starts = new difference_type[num_threads + 1];
|
||||
int bin_cursor = 0;
|
||||
sd.num_bins = num_bins;
|
||||
sd.num_bits = log2(num_bins);
|
||||
|
||||
difference_type chunk_length = n / num_threads, split = n % num_threads, start = 0;
|
||||
int bin_chunk_length = num_bins / num_threads, bin_split = num_bins % num_threads;
|
||||
for (int i = 0; i < num_threads; i++)
|
||||
{
|
||||
starts[i] = start;
|
||||
start += (i < split) ? (chunk_length + 1) : chunk_length;
|
||||
int j = pus[i].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.bin_proc[j] = i;
|
||||
pus[i].num_threads = num_threads;
|
||||
pus[i].iam = i;
|
||||
pus[i].seed = rng(std::numeric_limits<uint32>::max());
|
||||
pus[i].sd = &sd;
|
||||
}
|
||||
starts[num_threads] = start;
|
||||
|
||||
// Now shuffle in parallel.
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
parallel_random_shuffle_drs_pu(pus);
|
||||
|
||||
delete[] starts;
|
||||
delete[] sd.bin_proc;
|
||||
for (int s = 0; s < (num_bins + 1); s++)
|
||||
delete[] sd.dist[s];
|
||||
delete[] sd.dist;
|
||||
delete[] sd.temporaries;
|
||||
|
||||
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 RandomAccessIterator, typename RandomNumberGenerator>
|
||||
inline void
|
||||
sequential_random_shuffle(RandomAccessIterator begin, RandomAccessIterator end, RandomNumberGenerator& rng)
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
difference_type n = end - begin;
|
||||
|
||||
bin_index 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((difference_type)1, (difference_type)(n / (Settings::L1_cache_size_lb / sizeof(value_type))));
|
||||
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, (difference_type)num_bins_cache);
|
||||
#if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB
|
||||
// 2 TLB entries needed per bin
|
||||
num_bins = std::min((difference_type)Settings::TLB_size / 2, num_bins);
|
||||
#endif
|
||||
num_bins = round_up_to_pow2(num_bins);
|
||||
|
||||
if (num_bins < num_bins_cache)
|
||||
{
|
||||
#endif
|
||||
// Now try the L2 cache, must fit into L2.
|
||||
num_bins_cache = static_cast<bin_index>(std::max((difference_type)1, (difference_type)(n / (Settings::L2_cache_size / sizeof(value_type)))));
|
||||
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 = static_cast<bin_index>(std::min(n, (difference_type)num_bins_cache));
|
||||
|
||||
#if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_TLB
|
||||
// 2 TLB entries needed per bin
|
||||
num_bins = std::min((difference_type)Settings::TLB_size / 2, num_bins);
|
||||
#endif
|
||||
num_bins = round_up_to_pow2(num_bins);
|
||||
#if _GLIBCXX_RANDOM_SHUFFLE_CONSIDER_L1
|
||||
}
|
||||
#endif
|
||||
|
||||
int num_bits = log2(num_bins);
|
||||
|
||||
if (num_bins > 1)
|
||||
{
|
||||
value_type* target = new value_type[n];
|
||||
bin_index* oracles = new bin_index[n];
|
||||
difference_type* dist0 = new difference_type[num_bins + 1], * dist1 = new difference_type[num_bins + 1];
|
||||
|
||||
for (int b = 0; b < num_bins + 1; b++)
|
||||
dist0[b] = 0;
|
||||
|
||||
Timing<sequential_tag> t;
|
||||
t.tic();
|
||||
|
||||
random_number bitrng(rng(0xFFFFFFFF));
|
||||
|
||||
for (difference_type i = 0; i < n; i++)
|
||||
{
|
||||
bin_index oracle = random_number_pow2(num_bits, bitrng);
|
||||
oracles[i] = oracle;
|
||||
|
||||
// To allow prefix (partial) sum.
|
||||
dist0[oracle + 1]++;
|
||||
}
|
||||
|
||||
t.tic();
|
||||
|
||||
// Sum up bins.
|
||||
partial_sum(dist0, dist0 + num_bins + 1, dist0);
|
||||
|
||||
for (int b = 0; b < num_bins + 1; b++)
|
||||
dist1[b] = dist0[b];
|
||||
|
||||
t.tic();
|
||||
|
||||
// Distribute according to oracles.
|
||||
for (difference_type i = 0; i < n; i++)
|
||||
target[(dist0[oracles[i]])++] = *(begin + i);
|
||||
|
||||
for (int b = 0; b < num_bins; b++)
|
||||
{
|
||||
sequential_random_shuffle(target + dist1[b], target + dist1[b + 1],
|
||||
rng);
|
||||
t.tic();
|
||||
}
|
||||
t.print();
|
||||
|
||||
delete[] dist0;
|
||||
delete[] dist1;
|
||||
delete[] oracles;
|
||||
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 RandomAccessIterator, typename RandomNumberGenerator>
|
||||
inline void
|
||||
parallel_random_shuffle(RandomAccessIterator begin, RandomAccessIterator end, RandomNumberGenerator rng = random_number())
|
||||
{
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
difference_type n = end - begin;
|
||||
parallel_random_shuffle_drs(begin, end, n, get_max_threads(), rng) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
157
libstdc++-v3/include/parallel/search.h
Normal file
157
libstdc++-v3/include/parallel/search.h
Normal file
@ -0,0 +1,157 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/search.h
|
||||
* @brief Parallel implementation base for std::search() and
|
||||
* std::search_n().
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_SEARCH_H
|
||||
#define _GLIBCXX_PARALLEL_SEARCH_H 1
|
||||
|
||||
#include <bits/stl_algobase.h>
|
||||
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/equally_split.h>
|
||||
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/**
|
||||
* @brief Precalculate advances for Knuth-Morris-Pratt algorithm.
|
||||
* @param elements Begin iterator of sequence to search for.
|
||||
* @param length Length of sequence to search for.
|
||||
* @param advances Returned offsets.
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename _DifferenceTp>
|
||||
void
|
||||
calc_borders(RandomAccessIterator elements, _DifferenceTp length, _DifferenceTp* off)
|
||||
{
|
||||
typedef _DifferenceTp difference_type;
|
||||
|
||||
off[0] = -1;
|
||||
if (length > 1)
|
||||
off[1] = 0;
|
||||
difference_type k = 0;
|
||||
for (difference_type 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).
|
||||
|
||||
/** @brief Parallel std::search.
|
||||
* @param begin1 Begin iterator of first sequence.
|
||||
* @param end1 End iterator of first sequence.
|
||||
* @param begin2 Begin iterator of second sequence.
|
||||
* @param end2 End iterator of second sequence.
|
||||
* @param pred Find predicate.
|
||||
* @return Place of finding in first sequences. */
|
||||
template<typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename Pred>
|
||||
_RandomAccessIterator1
|
||||
search_template(_RandomAccessIterator1 begin1, _RandomAccessIterator1 end1,
|
||||
_RandomAccessIterator2 begin2, _RandomAccessIterator2 end2,
|
||||
Pred pred)
|
||||
{
|
||||
typedef std::iterator_traits<_RandomAccessIterator1> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
_GLIBCXX_CALL((end1 - begin1) + (end2 - begin2));
|
||||
|
||||
difference_type pattern_length = end2 - begin2;
|
||||
|
||||
// Pattern too short.
|
||||
if(pattern_length <= 0)
|
||||
return end1;
|
||||
|
||||
// Last point to start search.
|
||||
difference_type input_length = (end1 - begin1) - pattern_length;
|
||||
|
||||
// Where is first occurence of pattern? defaults to end.
|
||||
difference_type res = (end1 - begin1);
|
||||
|
||||
// Pattern too long.
|
||||
if (input_length < 0)
|
||||
return end1;
|
||||
|
||||
thread_index_t num_threads = std::max<difference_type>(1, std::min<difference_type>(input_length, __gnu_parallel::get_max_threads()));
|
||||
|
||||
difference_type borders[num_threads + 1];
|
||||
__gnu_parallel::equally_split(input_length, num_threads, borders);
|
||||
|
||||
difference_type advances[pattern_length];
|
||||
calc_borders(begin2, pattern_length, advances);
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
thread_index_t iam = omp_get_thread_num();
|
||||
|
||||
difference_type start = borders[iam], stop = borders[iam + 1];
|
||||
|
||||
difference_type pos_in_pattern = 0;
|
||||
bool found_pattern = false;
|
||||
|
||||
while (start <= stop && !found_pattern)
|
||||
{
|
||||
// Get new value of res.
|
||||
#pragma omp flush(res)
|
||||
// No chance for this thread to find first occurence.
|
||||
if (res < 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 res.
|
||||
#pragma omp critical (res)
|
||||
res = std::min(res, start);
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
// Return iterator on found element.
|
||||
return (begin1 + res);
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
#endif
|
529
libstdc++-v3/include/parallel/set_operations.h
Normal file
529
libstdc++-v3/include/parallel/set_operations.h
Normal file
@ -0,0 +1,529 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/**
|
||||
* @file parallel/set_operations.h
|
||||
* @brief Parallel implementations of set operations for random-access
|
||||
* iterators.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Marius Elvert and Felix Bondarenko.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_SET_OPERATIONS_H
|
||||
#define _GLIBCXX_PARALLEL_SET_OPERATIONS_H 1
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
#include <parallel/settings.h>
|
||||
#include <parallel/multiseq_selection.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator
|
||||
copy_tail(std::pair<InputIterator, InputIterator> b,
|
||||
std::pair<InputIterator, InputIterator> 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 InputIterator, typename OutputIterator, typename Comparator>
|
||||
struct symmetric_difference_func
|
||||
{
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
|
||||
|
||||
symmetric_difference_func(Comparator c) : comp(c) {}
|
||||
|
||||
Comparator comp;
|
||||
|
||||
inline OutputIterator invoke(InputIterator a, InputIterator b,
|
||||
InputIterator c, InputIterator d,
|
||||
OutputIterator r) const
|
||||
{
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{
|
||||
*r = *a;
|
||||
++a;
|
||||
++r;
|
||||
}
|
||||
else if (comp(*c, *a))
|
||||
{
|
||||
*r = *c;
|
||||
++c;
|
||||
++r;
|
||||
}
|
||||
else
|
||||
{
|
||||
++a;
|
||||
++c;
|
||||
}
|
||||
}
|
||||
return std::copy(c, d, std::copy(a, b, r));
|
||||
}
|
||||
|
||||
inline difference_type
|
||||
count(InputIterator a, InputIterator b, InputIterator c, InputIterator d) const
|
||||
{
|
||||
difference_type counter = 0;
|
||||
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{
|
||||
++a;
|
||||
++counter;
|
||||
}
|
||||
else if (comp(*c, *a))
|
||||
{
|
||||
++c;
|
||||
++counter;
|
||||
}
|
||||
else
|
||||
{
|
||||
++a;
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
return counter + (b - a) + (d - c);
|
||||
}
|
||||
|
||||
inline OutputIterator
|
||||
first_empty(InputIterator c, InputIterator d, OutputIterator out) const
|
||||
{ return std::copy(c, d, out); }
|
||||
|
||||
inline OutputIterator
|
||||
second_empty(InputIterator a, InputIterator b, OutputIterator out) const
|
||||
{ return std::copy(a, b, out); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename InputIterator, typename OutputIterator, typename Comparator>
|
||||
struct difference_func
|
||||
{
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
|
||||
|
||||
difference_func(Comparator c) : comp(c) {}
|
||||
|
||||
Comparator comp;
|
||||
|
||||
inline OutputIterator
|
||||
invoke(InputIterator a, InputIterator b, InputIterator c, InputIterator d,
|
||||
OutputIterator r) const
|
||||
{
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{
|
||||
*r = *a;
|
||||
++a;
|
||||
++r;
|
||||
}
|
||||
else if (comp(*c, *a))
|
||||
{ ++c; }
|
||||
else
|
||||
{
|
||||
++a;
|
||||
++c;
|
||||
}
|
||||
}
|
||||
return std::copy(a, b, r);
|
||||
}
|
||||
|
||||
inline difference_type
|
||||
count(InputIterator a, InputIterator b, InputIterator c, InputIterator d) const
|
||||
{
|
||||
difference_type counter = 0;
|
||||
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{
|
||||
++a;
|
||||
++counter;
|
||||
}
|
||||
else if (comp(*c, *a))
|
||||
{ ++c; }
|
||||
else
|
||||
{ ++a; ++c; }
|
||||
}
|
||||
|
||||
return counter + (b - a);
|
||||
}
|
||||
|
||||
inline OutputIterator
|
||||
first_empty(InputIterator c, InputIterator d, OutputIterator out) const
|
||||
{ return out; }
|
||||
|
||||
inline OutputIterator
|
||||
second_empty(InputIterator a, InputIterator b, OutputIterator out) const
|
||||
{ return std::copy(a, b, out); }
|
||||
};
|
||||
|
||||
|
||||
template<typename InputIterator, typename OutputIterator, typename Comparator>
|
||||
struct intersection_func
|
||||
{
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
|
||||
|
||||
intersection_func(Comparator c) : comp(c) {}
|
||||
|
||||
Comparator comp;
|
||||
|
||||
inline OutputIterator
|
||||
invoke(InputIterator a, InputIterator b, InputIterator c, InputIterator d,
|
||||
OutputIterator r) const
|
||||
{
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{ ++a; }
|
||||
else if (comp(*c, *a))
|
||||
{ ++c; }
|
||||
else
|
||||
{
|
||||
*r = *a;
|
||||
++a;
|
||||
++c;
|
||||
++r;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline difference_type
|
||||
count(InputIterator a, InputIterator b, InputIterator c, InputIterator d) const
|
||||
{
|
||||
difference_type counter = 0;
|
||||
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{ ++a; }
|
||||
else if (comp(*c, *a))
|
||||
{ ++c; }
|
||||
else
|
||||
{
|
||||
++a;
|
||||
++c;
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
inline OutputIterator
|
||||
first_empty(InputIterator c, InputIterator d, OutputIterator out) const
|
||||
{ return out; }
|
||||
|
||||
inline OutputIterator
|
||||
second_empty(InputIterator a, InputIterator b, OutputIterator out) const
|
||||
{ return out; }
|
||||
};
|
||||
|
||||
template<class InputIterator, class OutputIterator, class Comparator>
|
||||
struct union_func
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;
|
||||
|
||||
union_func(Comparator c) : comp(c) {}
|
||||
|
||||
Comparator comp;
|
||||
|
||||
inline OutputIterator
|
||||
invoke(InputIterator a, const InputIterator b, InputIterator c,
|
||||
const InputIterator d, OutputIterator r) const
|
||||
{
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{
|
||||
*r = *a;
|
||||
++a;
|
||||
}
|
||||
else if (comp(*c, *a))
|
||||
{
|
||||
*r = *c;
|
||||
++c;
|
||||
}
|
||||
else
|
||||
{
|
||||
*r = *a;
|
||||
++a;
|
||||
++c;
|
||||
}
|
||||
++r;
|
||||
}
|
||||
return std::copy(c, d, std::copy(a, b, r));
|
||||
}
|
||||
|
||||
inline difference_type
|
||||
count(InputIterator a, const InputIterator b, InputIterator c,
|
||||
const InputIterator d) const
|
||||
{
|
||||
difference_type counter = 0;
|
||||
|
||||
while (a != b && c != d)
|
||||
{
|
||||
if (comp(*a, *c))
|
||||
{ ++a; }
|
||||
else if (comp(*c, *a))
|
||||
{ ++c; }
|
||||
else
|
||||
{
|
||||
++a;
|
||||
++c;
|
||||
}
|
||||
++counter;
|
||||
}
|
||||
|
||||
counter += (b - a);
|
||||
counter += (d - c);
|
||||
return counter;
|
||||
}
|
||||
|
||||
inline OutputIterator
|
||||
first_empty(InputIterator c, InputIterator d, OutputIterator out) const
|
||||
{ return std::copy(c, d, out); }
|
||||
|
||||
inline OutputIterator
|
||||
second_empty(InputIterator a, InputIterator b, OutputIterator out) const
|
||||
{ return std::copy(a, b, out); }
|
||||
};
|
||||
|
||||
template<typename InputIterator, typename OutputIterator, typename Operation>
|
||||
OutputIterator
|
||||
parallel_set_operation(InputIterator begin1, InputIterator end1,
|
||||
InputIterator begin2, InputIterator end2,
|
||||
OutputIterator result, Operation op)
|
||||
{
|
||||
_GLIBCXX_CALL((end1 - begin1) + (end2 - begin2))
|
||||
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
typedef typename std::pair<InputIterator, InputIterator> iterator_pair;
|
||||
|
||||
|
||||
if (begin1 == end1)
|
||||
return op.first_empty(begin2, end2, result);
|
||||
|
||||
if (begin2 == end2)
|
||||
return op.second_empty(begin1, end1, result);
|
||||
|
||||
const difference_type size = (end1 - begin1) + (end2 - begin2);
|
||||
|
||||
thread_index_t num_threads = std::min<difference_type>(std::min(end1 - begin1, end2 - begin2), get_max_threads());
|
||||
|
||||
difference_type borders[num_threads + 2];
|
||||
equally_split(size, num_threads + 1, borders);
|
||||
|
||||
const iterator_pair sequence[ 2 ] = { std::make_pair(begin1, end1), std::make_pair(begin2, end2) } ;
|
||||
|
||||
iterator_pair block_begins[num_threads + 1];
|
||||
|
||||
// Very start.
|
||||
block_begins[0] = std::make_pair(begin1, begin2);
|
||||
difference_type length[num_threads];
|
||||
|
||||
OutputIterator return_value = result;
|
||||
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
Timing<sequential_tag> t;
|
||||
|
||||
t.tic();
|
||||
|
||||
// Result from multiseq_partition.
|
||||
InputIterator offset[2];
|
||||
const int iam = omp_get_thread_num();
|
||||
|
||||
const difference_type rank = borders[iam + 1];
|
||||
|
||||
multiseq_partition(sequence, sequence + 2, rank, offset, op.comp);
|
||||
|
||||
// allowed to read?
|
||||
// together
|
||||
// *(offset[ 0 ] - 1) == *offset[ 1 ]
|
||||
if (offset[ 0 ] != begin1 && offset[ 1 ] != end2
|
||||
&& !op.comp(*(offset[ 0 ] - 1), *offset[ 1 ])
|
||||
&& !op.comp(*offset[ 1 ], *(offset[ 0 ] - 1)))
|
||||
{
|
||||
// Avoid split between globally equal elements: move one to
|
||||
// front in first sequence.
|
||||
--offset[ 0 ];
|
||||
}
|
||||
|
||||
iterator_pair block_end = block_begins[ iam + 1 ] = iterator_pair(offset[ 0 ], offset[ 1 ]);
|
||||
|
||||
t.tic();
|
||||
|
||||
// Make sure all threads have their block_begin result written out.
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic();
|
||||
|
||||
iterator_pair 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.
|
||||
length[ iam ] = op.invoke(block_begin.first, block_end.first, block_begin.second, block_end.second, result) - result;
|
||||
}
|
||||
else
|
||||
{
|
||||
length[ iam ] = op.count(block_begin.first, block_end.first,
|
||||
block_begin.second, block_end.second);
|
||||
}
|
||||
|
||||
t.tic();
|
||||
|
||||
// Make sure everyone wrote their lengths.
|
||||
#pragma omp barrier
|
||||
|
||||
t.tic();
|
||||
OutputIterator r = result;
|
||||
|
||||
if (iam == 0)
|
||||
{
|
||||
// Do the last block.
|
||||
for (int i = 0; i < num_threads; ++i)
|
||||
r += length[i];
|
||||
|
||||
block_begin = block_begins[num_threads];
|
||||
|
||||
// Return the result iterator of the last block.
|
||||
return_value = op.invoke(block_begin.first, end1, block_begin.second, end2, r);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < iam; ++i)
|
||||
r += length[ i ];
|
||||
|
||||
// Reset begins for copy pass.
|
||||
op.invoke(block_begin.first, block_end.first,
|
||||
block_begin.second, block_end.second, r);
|
||||
}
|
||||
|
||||
t.tic();
|
||||
t.print();
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
|
||||
template<typename InputIterator, typename OutputIterator, typename Comparator>
|
||||
OutputIterator
|
||||
parallel_set_union(InputIterator begin1, InputIterator end1,
|
||||
InputIterator begin2, InputIterator end2,
|
||||
OutputIterator result, Comparator comp)
|
||||
{
|
||||
return parallel_set_operation(begin1, end1, begin2, end2, result,
|
||||
union_func< InputIterator, OutputIterator, Comparator>(comp));
|
||||
}
|
||||
|
||||
template<typename InputIterator, typename OutputIterator, typename Comparator>
|
||||
OutputIterator
|
||||
parallel_set_intersection(InputIterator begin1, InputIterator end1,
|
||||
InputIterator begin2, InputIterator end2,
|
||||
OutputIterator result, Comparator comp)
|
||||
{
|
||||
return parallel_set_operation(begin1, end1, begin2, end2, result,
|
||||
intersection_func<InputIterator, OutputIterator, Comparator>(comp));
|
||||
}
|
||||
|
||||
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
OutputIterator
|
||||
set_intersection(InputIterator begin1, InputIterator end1, InputIterator begin2, InputIterator end2, OutputIterator result)
|
||||
{
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
|
||||
return set_intersection(begin1, end1, begin2, end2, result,
|
||||
std::less<value_type>());
|
||||
}
|
||||
|
||||
template<typename InputIterator, typename OutputIterator, typename Comparator>
|
||||
OutputIterator
|
||||
parallel_set_difference(InputIterator begin1, InputIterator end1,
|
||||
InputIterator begin2, InputIterator end2,
|
||||
OutputIterator result, Comparator comp)
|
||||
{
|
||||
return parallel_set_operation(begin1, end1, begin2, end2, result,
|
||||
difference_func<InputIterator, OutputIterator, Comparator>(comp));
|
||||
}
|
||||
|
||||
template<typename InputIterator, typename OutputIterator, typename Comparator>
|
||||
OutputIterator
|
||||
parallel_set_symmetric_difference(InputIterator begin1, InputIterator end1, InputIterator begin2, InputIterator end2, OutputIterator result, Comparator comp)
|
||||
{
|
||||
return parallel_set_operation(begin1, end1, begin2, end2, result,
|
||||
symmetric_difference_func<InputIterator, OutputIterator, Comparator>(comp));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _GLIBCXX_SET_ALGORITHM_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
388
libstdc++-v3/include/parallel/settings.h
Normal file
388
libstdc++-v3/include/parallel/settings.h
Normal file
@ -0,0 +1,388 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/settings.h
|
||||
* @brief Settings and tuning parameters, heuristics to decide
|
||||
* whether to use parallelized algorithms.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*
|
||||
* @section parallelization_decision The decision whether to run an algorithm in parallel.
|
||||
*
|
||||
* There are several ways the user can switch on and off the
|
||||
* parallel execution of an algorithm, both at compile- and
|
||||
* run-time.
|
||||
*
|
||||
* Only sequential execution can be forced at compile-time.
|
||||
* This reduces code size and protects code parts that have
|
||||
* non-thread-safe side effects.
|
||||
*
|
||||
* Ultimately forcing parallel execution at compile-time does
|
||||
* make much sense.
|
||||
* Often, the sequential algorithm implementation is used as
|
||||
* a subroutine, so no reduction in code size can be achieved.
|
||||
* Also, the machine the program is run on might have only one
|
||||
* processor core, so to avoid overhead, the algorithm is
|
||||
* executed sequentially.
|
||||
*
|
||||
* To force sequential execution of an algorithm ultimately
|
||||
* at compile-time, the user must add the tag
|
||||
* __gnu_parallel::sequential_tag() to the end of the
|
||||
* parameter list, e. g.
|
||||
*
|
||||
* \code
|
||||
* std::sort(v.begin(), v.end(), __gnu_parallel::sequential_tag());
|
||||
* \endcode
|
||||
*
|
||||
* This is compatible with all overloaded algorithm variants.
|
||||
* No additional code will be instantiated, at all.
|
||||
* The same holds for most algorithm calls with iterators
|
||||
* not providing random access.
|
||||
*
|
||||
* If the algorithm call is not forced to be executed sequentially
|
||||
* at compile-time, the decision is made at run-time, for each call.
|
||||
* First, the two (conceptually) global variables
|
||||
* __gnu_parallel::Settings::force_sequential and
|
||||
* __gnu_parallel::Settings::force_parallel are executed.
|
||||
* If the former one is true, the sequential algorithm is executed.
|
||||
* If the latter one is true and the former one is false,
|
||||
* the algorithm is executed in parallel.
|
||||
*
|
||||
* If none of these conditions has fired so far, a heuristic is used.
|
||||
* The parallel algorithm implementation is called only if the
|
||||
* input size is sufficiently large.
|
||||
* For most algorithms, the input size is the (combined) length of
|
||||
* the input sequence(s).
|
||||
* The threshold can be set by the user, individually for each
|
||||
* algorithm.
|
||||
* The according variables are called
|
||||
* __gnu_parallel::Settings::[algorithm]_minimal_n .
|
||||
*
|
||||
* For some of the algorithms, there are even more tuning options,
|
||||
* e. g. the ability to choose from multiple algorithm variants.
|
||||
* See the __gnu_parallel::Settings class for details.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler and Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_SETTINGS_H
|
||||
#define _GLIBCXX_PARALLEL_SETTINGS_H 1
|
||||
|
||||
#include <omp.h>
|
||||
#include <parallel/types.h>
|
||||
|
||||
/**
|
||||
* @brief The extensible condition on whether the parallel variant of
|
||||
* an algorithm sould be called.
|
||||
* @param c A condition that is overruled by
|
||||
* __gnu_parallel::Settings::force_parallel, i. e. usually a decision based on
|
||||
* the input size.
|
||||
*/
|
||||
#define _GLIBCXX_PARALLEL_CONDITION(c) (!(__gnu_parallel::Settings::force_sequential) && ((__gnu_parallel::get_max_threads() > 1 && (c)) || __gnu_parallel::Settings::force_parallel))
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
// NB: Including this file cannot produce (unresolved) symbols from
|
||||
// the OpenMP runtime unless the parallel mode is actually invoked
|
||||
// and active, which imples that the OpenMP runtime is actually
|
||||
// going to be linked in.
|
||||
inline int
|
||||
get_max_threads()
|
||||
{ return omp_get_max_threads() > 1 ? omp_get_max_threads() : 1; }
|
||||
|
||||
namespace
|
||||
{
|
||||
// XXX look at _Tune in mt_allocator.h
|
||||
/** @brief Run-time settings for the parallel mode. */
|
||||
struct Settings
|
||||
{
|
||||
/** @brief Different parallel sorting algorithms to choose
|
||||
from: multi-way mergesort, quicksort, load-balanced
|
||||
quicksort. */
|
||||
enum SortAlgorithm
|
||||
{ MWMS, QS, QS_BALANCED };
|
||||
|
||||
/** @brief Different merging algorithms: bubblesort-alike,
|
||||
loser-tree variants, enum sentinel */
|
||||
enum MultiwayMergeAlgorithm
|
||||
{ BUBBLE, LOSER_TREE_EXPLICIT, LOSER_TREE, LOSER_TREE_COMBINED, LOSER_TREE_SENTINEL, MWM_ALGORITHM_LAST };
|
||||
|
||||
/** @brief Different splitting strategies for sorting/merging:
|
||||
by sampling, exact */
|
||||
enum Splitting
|
||||
{ SAMPLING, EXACT };
|
||||
|
||||
/** @brief Different partial sum algorithms: recursive, linear */
|
||||
enum PartialSumAlgorithm
|
||||
{ RECURSIVE, LINEAR };
|
||||
|
||||
/** @brief Different find distribution strategies: growing
|
||||
blocks, equal-sized blocks, equal splitting. */
|
||||
enum FindDistribution
|
||||
{ GROWING_BLOCKS, CONSTANT_SIZE_BLOCKS, EQUAL_SPLIT };
|
||||
|
||||
/** @brief Force all algorithms to be executed sequentially.
|
||||
* This setting cannot be overwritten. */
|
||||
static volatile bool force_sequential;
|
||||
|
||||
/** @brief Force all algorithms to be executed in parallel.
|
||||
* This setting can be overriden by __gnu_parallel::sequential_tag
|
||||
* (compile-time), and force_sequential (run-time). */
|
||||
static volatile bool force_parallel;
|
||||
|
||||
/** @brief Algorithm to use for sorting. */
|
||||
static volatile SortAlgorithm sort_algorithm;
|
||||
|
||||
/** @brief Strategy to use for splitting the input when
|
||||
sorting (MWMS). */
|
||||
static volatile Splitting sort_splitting;
|
||||
|
||||
/** @brief Minimal input size for parallel sorting. */
|
||||
static volatile sequence_index_t sort_minimal_n;
|
||||
/** @brief Oversampling factor for parallel std::sort (MWMS). */
|
||||
static volatile unsigned int sort_mwms_oversampling;
|
||||
/** @brief Such many samples to take to find a good pivot
|
||||
(quicksort). */
|
||||
static volatile unsigned int sort_qs_num_samples_preset;
|
||||
|
||||
/** @brief Maximal subsequence length to swtich to unbalanced
|
||||
* base case. Applies to std::sort with dynamically
|
||||
* load-balanced quicksort. */
|
||||
static volatile sequence_index_t sort_qsb_base_case_maximal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::partition. */
|
||||
static volatile sequence_index_t partition_minimal_n;
|
||||
|
||||
/** @brief Chunk size for parallel std::partition. */
|
||||
static volatile sequence_index_t partition_chunk_size;
|
||||
|
||||
/** @brief Chunk size for parallel std::partition, relative to
|
||||
* input size. If >0.0, this value overrides
|
||||
* partition_chunk_size. */
|
||||
static volatile double partition_chunk_share;
|
||||
|
||||
/** @brief Minimal input size for parallel std::nth_element. */
|
||||
static volatile sequence_index_t nth_element_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::partial_sort. */
|
||||
static volatile sequence_index_t partial_sort_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::adjacent_difference. */
|
||||
static volatile unsigned int adjacent_difference_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::partial_sum. */
|
||||
static volatile unsigned int partial_sum_minimal_n;
|
||||
|
||||
/** @brief Algorithm to use for std::partial_sum. */
|
||||
static volatile PartialSumAlgorithm partial_sum_algorithm;
|
||||
|
||||
/** @brief Assume "sum and write result" to be that factor
|
||||
* slower than just "sum". This value is used for
|
||||
* std::partial_sum. */
|
||||
static volatile float partial_sum_dilatation;
|
||||
|
||||
/** @brief Minimal input size for parallel std::random_shuffle. */
|
||||
static volatile unsigned int random_shuffle_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::merge. */
|
||||
static volatile sequence_index_t merge_minimal_n;
|
||||
|
||||
/** @brief Splitting strategy for parallel std::merge. */
|
||||
static volatile Splitting merge_splitting;
|
||||
|
||||
/** @brief Oversampling factor for parallel std::merge.
|
||||
* Such many samples per thread are collected. */
|
||||
static volatile unsigned int merge_oversampling;
|
||||
|
||||
/** @brief Algorithm to use for parallel
|
||||
__gnu_parallel::multiway_merge. */
|
||||
static volatile MultiwayMergeAlgorithm multiway_merge_algorithm;
|
||||
|
||||
/** @brief Splitting strategy to use for parallel
|
||||
__gnu_parallel::multiway_merge. */
|
||||
static volatile Splitting multiway_merge_splitting;
|
||||
|
||||
//// Oversampling factor for parallel __gnu_parallel::multiway_merge.
|
||||
static volatile unsigned int multiway_merge_oversampling;
|
||||
|
||||
/// Minimal input size for parallel __gnu_parallel::multiway_merge.
|
||||
static volatile sequence_index_t multiway_merge_minimal_n;
|
||||
|
||||
/// Oversampling factor for parallel __gnu_parallel::multiway_merge.
|
||||
static volatile int multiway_merge_minimal_k;
|
||||
|
||||
/** @brief Minimal input size for parallel std::unique_copy. */
|
||||
static volatile sequence_index_t unique_copy_minimal_n;
|
||||
|
||||
static volatile sequence_index_t workstealing_chunk_size;
|
||||
|
||||
/** @brief Minimal input size for parallel std::for_each. */
|
||||
static volatile sequence_index_t for_each_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::count and
|
||||
std::count_if. */
|
||||
static volatile sequence_index_t count_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::transform. */
|
||||
static volatile sequence_index_t transform_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::replace and
|
||||
std::replace_if. */
|
||||
static volatile sequence_index_t replace_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::generate. */
|
||||
static volatile sequence_index_t generate_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::fill. */
|
||||
static volatile sequence_index_t fill_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::min_element. */
|
||||
static volatile sequence_index_t min_element_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::max_element. */
|
||||
static volatile sequence_index_t max_element_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::accumulate. */
|
||||
static volatile sequence_index_t accumulate_minimal_n;
|
||||
|
||||
/** @brief Distribution strategy for parallel std::find. */
|
||||
static volatile FindDistribution find_distribution;
|
||||
|
||||
/** @brief Start with looking for that many elements
|
||||
sequentially, for std::find. */
|
||||
static volatile sequence_index_t find_sequential_search_size;
|
||||
|
||||
/** @brief Initial block size for parallel std::find. */
|
||||
static volatile sequence_index_t find_initial_block_size;
|
||||
|
||||
/** @brief Maximal block size for parallel std::find. */
|
||||
static volatile sequence_index_t find_maximum_block_size;
|
||||
|
||||
/** @brief Block size increase factor for parallel std::find. */
|
||||
static volatile double find_increasing_factor;
|
||||
|
||||
//set operations
|
||||
/** @brief Minimal input size for parallel std::set_union. */
|
||||
static volatile sequence_index_t set_union_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel
|
||||
std::set_symmetric_difference. */
|
||||
static volatile sequence_index_t set_symmetric_difference_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::set_difference. */
|
||||
static volatile sequence_index_t set_difference_minimal_n;
|
||||
|
||||
/** @brief Minimal input size for parallel std::set_intersection. */
|
||||
static volatile sequence_index_t set_intersection_minimal_n;
|
||||
|
||||
//hardware dependent tuning parameters
|
||||
/** @brief Size of the L1 cache in bytes (underestimation). */
|
||||
static volatile unsigned long long L1_cache_size;
|
||||
|
||||
/** @brief Size of the L2 cache in bytes (underestimation). */
|
||||
static volatile unsigned long long L2_cache_size;
|
||||
|
||||
/** @brief Size of the Translation Lookaside Buffer
|
||||
(underestimation). */
|
||||
static volatile unsigned int TLB_size;
|
||||
|
||||
/** @brief Overestimation of cache line size. Used to avoid
|
||||
* false sharing, i. e. elements of different threads are at
|
||||
* least this amount apart. */
|
||||
static unsigned int cache_line_size;
|
||||
|
||||
//statistics
|
||||
/** @brief Statistic on the number of stolen ranges in
|
||||
load-balanced quicksort.*/
|
||||
static volatile sequence_index_t qsb_steals;
|
||||
};
|
||||
|
||||
volatile bool Settings::force_parallel = false;
|
||||
volatile bool Settings::force_sequential = false;
|
||||
volatile Settings::SortAlgorithm Settings::sort_algorithm = Settings::MWMS;
|
||||
volatile Settings::Splitting Settings::sort_splitting = Settings::EXACT;
|
||||
volatile sequence_index_t Settings::sort_minimal_n = 1000;
|
||||
|
||||
volatile unsigned int Settings::sort_mwms_oversampling = 10;
|
||||
volatile unsigned int Settings::sort_qs_num_samples_preset = 100;
|
||||
volatile sequence_index_t Settings::sort_qsb_base_case_maximal_n = 100;
|
||||
volatile sequence_index_t Settings::partition_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::nth_element_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::partial_sort_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::partition_chunk_size = 1000;
|
||||
volatile double Settings::partition_chunk_share = 0.0;
|
||||
volatile unsigned int Settings::adjacent_difference_minimal_n = 1000;
|
||||
volatile Settings::PartialSumAlgorithm Settings::partial_sum_algorithm = Settings::LINEAR;
|
||||
volatile unsigned int Settings::partial_sum_minimal_n = 1000;
|
||||
volatile float Settings::partial_sum_dilatation = 1.0f;
|
||||
volatile unsigned int Settings::random_shuffle_minimal_n = 1000;
|
||||
volatile Settings::Splitting Settings::merge_splitting = Settings::EXACT;
|
||||
volatile sequence_index_t Settings::merge_minimal_n = 1000;
|
||||
volatile unsigned int Settings::merge_oversampling = 10;
|
||||
volatile sequence_index_t Settings::multiway_merge_minimal_n = 1000;
|
||||
volatile int Settings::multiway_merge_minimal_k = 2;
|
||||
|
||||
// unique copy
|
||||
volatile sequence_index_t Settings::unique_copy_minimal_n = 10000;
|
||||
volatile Settings::MultiwayMergeAlgorithm Settings::multiway_merge_algorithm = Settings::LOSER_TREE;
|
||||
volatile Settings::Splitting Settings::multiway_merge_splitting = Settings::EXACT;
|
||||
volatile unsigned int Settings::multiway_merge_oversampling = 10;
|
||||
volatile Settings::FindDistribution Settings::find_distribution = Settings::CONSTANT_SIZE_BLOCKS;
|
||||
volatile sequence_index_t Settings::find_sequential_search_size = 256;
|
||||
volatile sequence_index_t Settings::find_initial_block_size = 256;
|
||||
volatile sequence_index_t Settings::find_maximum_block_size = 8192;
|
||||
volatile double Settings::find_increasing_factor = 2.0;
|
||||
volatile sequence_index_t Settings::workstealing_chunk_size = 100;
|
||||
volatile sequence_index_t Settings::for_each_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::count_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::transform_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::replace_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::generate_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::fill_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::min_element_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::max_element_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::accumulate_minimal_n = 1000;
|
||||
|
||||
//set operations
|
||||
volatile sequence_index_t Settings::set_union_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::set_intersection_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::set_difference_minimal_n = 1000;
|
||||
volatile sequence_index_t Settings::set_symmetric_difference_minimal_n = 1000;
|
||||
volatile unsigned long long Settings::L1_cache_size = 16 << 10;
|
||||
volatile unsigned long long Settings::L2_cache_size = 256 << 10;
|
||||
volatile unsigned int Settings::TLB_size = 128;
|
||||
unsigned int Settings::cache_line_size = 64;
|
||||
|
||||
//statistics
|
||||
volatile sequence_index_t Settings::qsb_steals = 0;
|
||||
} // end anonymous namespace
|
||||
|
||||
}
|
||||
|
||||
#endif /* _GLIBCXX_SETTINGS_H */
|
104
libstdc++-v3/include/parallel/sort.h
Normal file
104
libstdc++-v3/include/parallel/sort.h
Normal file
@ -0,0 +1,104 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/sort.h
|
||||
* @brief Parallel sorting algorithm switch.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_SORT_H
|
||||
#define _GLIBCXX_PARALLEL_SORT_H 1
|
||||
|
||||
#include <parallel/basic_iterator.h>
|
||||
#include <parallel/features.h>
|
||||
#include <parallel/parallel.h>
|
||||
|
||||
#if _GLIBCXX_ASSERTIONS
|
||||
#include <parallel/checkers.h>
|
||||
#endif
|
||||
|
||||
#if _GLIBCXX_MERGESORT
|
||||
#include <parallel/multiway_mergesort.h>
|
||||
#endif
|
||||
|
||||
#if _GLIBCXX_QUICKSORT
|
||||
#include <parallel/quicksort.h>
|
||||
#endif
|
||||
|
||||
#if _GLIBCXX_BAL_QUICKSORT
|
||||
#include <parallel/balanced_quicksort.h>
|
||||
#endif
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
/**
|
||||
* @brief Choose a parallel sorting algorithm.
|
||||
* @param begin Begin iterator of input sequence.
|
||||
* @param end End iterator of input sequence.
|
||||
* @param comp Comparator.
|
||||
* @param stable Sort stable.
|
||||
* @callgraph
|
||||
*/
|
||||
template<typename RandomAccessIterator, typename Comparator>
|
||||
inline void
|
||||
parallel_sort(RandomAccessIterator begin, RandomAccessIterator end,
|
||||
Comparator comp, bool stable)
|
||||
{
|
||||
_GLIBCXX_CALL(end - begin)
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
difference_type n = end - begin;
|
||||
|
||||
if (false) ;
|
||||
#if _GLIBCXX_MERGESORT
|
||||
else if (Settings::sort_algorithm == Settings::MWMS || stable)
|
||||
parallel_sort_mwms(begin, end, comp, n, get_max_threads(), stable);
|
||||
#endif
|
||||
#if _GLIBCXX_QUICKSORT
|
||||
else if (Settings::sort_algorithm == Settings::QS && !stable)
|
||||
parallel_sort_qs(begin, end, comp, n, get_max_threads());
|
||||
#endif
|
||||
#if _GLIBCXX_BAL_QUICKSORT
|
||||
else if (Settings::sort_algorithm == Settings::QS_BALANCED && !stable)
|
||||
parallel_sort_qsb(begin, end, comp, n, get_max_threads());
|
||||
#endif
|
||||
else
|
||||
__gnu_sequential::sort(begin, end, comp);
|
||||
}
|
||||
}
|
||||
} // end namespace __gnu_parallel
|
||||
|
||||
#endif
|
124
libstdc++-v3/include/parallel/tags.h
Normal file
124
libstdc++-v3/include/parallel/tags.h
Normal file
@ -0,0 +1,124 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/**
|
||||
* @file parallel/tags.h
|
||||
* @brief Tags for compile-time options.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler and Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_TAGS_H
|
||||
#define _GLIBCXX_PARALLEL_TAGS_H 1
|
||||
|
||||
// Parallel mode namespaces.
|
||||
namespace std
|
||||
{
|
||||
namespace __parallel { }
|
||||
}
|
||||
|
||||
/**
|
||||
* @namespace __gnu_sequential
|
||||
* @brief GNU sequential classes for public use.
|
||||
*/
|
||||
namespace __gnu_sequential { }
|
||||
|
||||
/**
|
||||
* @namespace __gnu_parallel
|
||||
* @brief GNU parallel classes for public use.
|
||||
*/
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
// Import all the parallel versions of components in namespace std.
|
||||
using namespace std::__parallel;
|
||||
|
||||
enum parallelism
|
||||
{
|
||||
/// Not parallel.
|
||||
sequential,
|
||||
|
||||
/// Parallel unbalanced (equal-sized chunks).
|
||||
parallel_unbalanced,
|
||||
|
||||
/// Parallel balanced (work-stealing).
|
||||
parallel_balanced,
|
||||
|
||||
/// Parallel with OpenMP dynamic load-balancing.
|
||||
parallel_omp_loop,
|
||||
|
||||
/// Parallel with OpenMP static load-balancing.
|
||||
parallel_omp_loop_static,
|
||||
|
||||
/// Parallel with OpenMP taskqueue construct.
|
||||
parallel_taskqueue
|
||||
};
|
||||
|
||||
inline bool
|
||||
is_parallel(const parallelism __p) { return __p != sequential; }
|
||||
|
||||
|
||||
/** @brief Forces sequential execution at compile time. */
|
||||
struct sequential_tag { };
|
||||
|
||||
/** @brief Recommends parallel execution at compile time. */
|
||||
struct parallel_tag { };
|
||||
|
||||
/** @brief Recommends parallel execution using dynamic
|
||||
load-balancing at compile time. */
|
||||
struct balanced_tag : public parallel_tag { };
|
||||
|
||||
/** @brief Recommends parallel execution using static
|
||||
load-balancing at compile time. */
|
||||
struct unbalanced_tag : public parallel_tag { };
|
||||
|
||||
/** @brief Recommends parallel execution using OpenMP dynamic
|
||||
load-balancing at compile time. */
|
||||
struct omp_loop_tag : public parallel_tag { };
|
||||
|
||||
/** @brief Recommends parallel execution using OpenMP static
|
||||
load-balancing at compile time. */
|
||||
struct omp_loop_static_tag : public parallel_tag { };
|
||||
|
||||
|
||||
/** @brief Selects the growing block size variant for std::find().
|
||||
@see _GLIBCXX_FIND_GROWING_BLOCKS */
|
||||
struct growing_blocks_tag { };
|
||||
|
||||
/** @brief Selects the constant block size variant for std::find().
|
||||
@see _GLIBCXX_FIND_CONSTANT_SIZE_BLOCKS */
|
||||
struct constant_size_blocks_tag { };
|
||||
|
||||
/** @brief Selects the equal splitting variant for std::find().
|
||||
@see _GLIBCXX_FIND_EQUAL_SPLIT */
|
||||
struct equal_split_tag { };
|
||||
}
|
||||
|
||||
#endif /* _GLIBCXX_TAGS_H */
|
217
libstdc++-v3/include/parallel/timing.h
Normal file
217
libstdc++-v3/include/parallel/timing.h
Normal file
@ -0,0 +1,217 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/timing.h
|
||||
* @brief Provides a simple tool to do performance debugging, also in
|
||||
* parallel code.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_TIMING_H
|
||||
#define _GLIBCXX_PARALLEL_TIMING_H 1
|
||||
|
||||
#include <omp.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <parallel/tags.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
// XXX integrate with existing performance testing infrastructure.
|
||||
/** @brief Type of of point in time, used for the Timing classes. */
|
||||
typedef double point_in_time;
|
||||
|
||||
template<typename tag, typename must_be_int = int>
|
||||
class Timing;
|
||||
|
||||
/** @brief A class that provides simple run time measurements, also
|
||||
for parallel code.
|
||||
* @param tag If parallel_tag, then the measurements are actually done.
|
||||
* Otherwise, no code at all is emitted by the compiler. */
|
||||
template<typename must_be_int>
|
||||
class Timing<parallel_tag, must_be_int>
|
||||
{
|
||||
private:
|
||||
static const int max_points_in_time = 100;
|
||||
point_in_time points_in_time[max_points_in_time];
|
||||
point_in_time active, last_start;
|
||||
int pos;
|
||||
char* str;
|
||||
const char* tags[max_points_in_time];
|
||||
|
||||
public:
|
||||
Timing()
|
||||
{
|
||||
str = NULL;
|
||||
pos = 0;
|
||||
active = 0.0;
|
||||
last_start = -1.0;
|
||||
}
|
||||
|
||||
~Timing()
|
||||
{
|
||||
delete[] str;
|
||||
}
|
||||
|
||||
/** @brief Take a running time measurement.
|
||||
* @param tag Optional description that will be output again with
|
||||
* the timings.
|
||||
* It should describe the operation before the tic(). To time a
|
||||
* series of @c n operations, there should be @c n+1 calls to
|
||||
* tic(), and one call to print(). */
|
||||
inline void
|
||||
tic(const char* tag = NULL)
|
||||
{
|
||||
points_in_time[pos] = omp_get_wtime();
|
||||
tags[pos] = tag;
|
||||
pos++;
|
||||
}
|
||||
|
||||
/** @brief Start the running time measurement.
|
||||
*
|
||||
* Should be paired with stop(). */
|
||||
inline void
|
||||
start()
|
||||
{
|
||||
_GLIBCXX_PARALLEL_ASSERT(last_start == -1.0);
|
||||
last_start = omp_get_wtime();
|
||||
}
|
||||
|
||||
/** @brief Stop the running time measurement.
|
||||
*
|
||||
* Should be paired with start(). */
|
||||
inline void
|
||||
stop()
|
||||
{
|
||||
_GLIBCXX_PARALLEL_ASSERT(last_start != -1.0);
|
||||
active += (omp_get_wtime() - last_start);
|
||||
last_start = -1.0;
|
||||
}
|
||||
|
||||
/** @brief Reset running time accumulation. */
|
||||
inline void
|
||||
reset()
|
||||
{
|
||||
active = 0.0;
|
||||
last_start = -1.0;
|
||||
}
|
||||
|
||||
/** @brief Accumulate the time between all pairs of start() and
|
||||
stop() so far */
|
||||
inline point_in_time
|
||||
active_time()
|
||||
{ return active; }
|
||||
|
||||
/** @brief Total time between first and last tic() */
|
||||
inline point_in_time
|
||||
total_time()
|
||||
{ return (points_in_time[pos - 1] - points_in_time[0]) * 1000.0; }
|
||||
|
||||
private:
|
||||
/** @brief Construct string to print out, presenting the timings. */
|
||||
const char*
|
||||
c_str()
|
||||
{
|
||||
// Avoid stream library here, to avoid cyclic dependencies in
|
||||
// header files.
|
||||
char tmp[1000];
|
||||
|
||||
if (!str)
|
||||
str = new char[pos * 200];
|
||||
else
|
||||
str[0] = '\0';
|
||||
|
||||
sprintf(str, "t %2d T[ms]", omp_get_thread_num());
|
||||
strcat(str, "\n");
|
||||
|
||||
for (int i = 0; i < pos; )
|
||||
{
|
||||
point_in_time last = points_in_time[i];
|
||||
i++;
|
||||
if (i == pos)
|
||||
break;
|
||||
if (tags[i] == NULL)
|
||||
sprintf(tmp, "%2d: ", i - 1);
|
||||
else
|
||||
sprintf(tmp, "%20s: ", tags[i]);
|
||||
strcat(str, tmp);
|
||||
|
||||
sprintf(tmp, "%7.2f ", (points_in_time[i] - last) * 1000.0);
|
||||
strcat(str, tmp);
|
||||
strcat(str, "\n");
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
public:
|
||||
/** @brief Print the running times between the tic()s. */
|
||||
void
|
||||
print()
|
||||
{
|
||||
printf("print\n");
|
||||
#pragma omp barrier
|
||||
#pragma omp master
|
||||
printf("\n\n");
|
||||
#pragma omp critical
|
||||
printf("%s\n", c_str());
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief A class that provides simple run time measurements, also
|
||||
for parallel code.
|
||||
* @param tag If parallel_tag, then the measurements are actually done,
|
||||
* otherwise, no code at all is emitted by the compiler.
|
||||
*/
|
||||
template<typename must_be_int>
|
||||
class Timing<sequential_tag, must_be_int>
|
||||
{
|
||||
private:
|
||||
static const char* empty_string;
|
||||
|
||||
public:
|
||||
inline void tic(const char* /*tag*/ = NULL) { }
|
||||
inline void start() { }
|
||||
inline void stop() { }
|
||||
inline void reset() { }
|
||||
inline point_in_time active_time() { return -1.0; }
|
||||
inline point_in_time total_time() { return -1.0; }
|
||||
inline const char* c_str() { return empty_string; }
|
||||
inline void print() { }
|
||||
};
|
||||
|
||||
template<typename must_be_int>
|
||||
const char* Timing<sequential_tag, must_be_int>::empty_string = "";
|
||||
|
||||
}
|
||||
|
||||
#endif
|
3574
libstdc++-v3/include/parallel/tree.h
Normal file
3574
libstdc++-v3/include/parallel/tree.h
Normal file
File diff suppressed because it is too large
Load Diff
98
libstdc++-v3/include/parallel/types.h
Normal file
98
libstdc++-v3/include/parallel/types.h
Normal file
@ -0,0 +1,98 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/types.h
|
||||
* @brief Basic typedefs.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Johannes Singler and Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_TYPES_H
|
||||
#define _GLIBCXX_PARALLEL_TYPES_H 1
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
// XXX need to use <cstdint>
|
||||
/** @brief 8-bit signed integer. */
|
||||
typedef char int8;
|
||||
|
||||
/** @brief 8-bit unsigned integer. */
|
||||
typedef unsigned char uint8;
|
||||
|
||||
/** @brief 16-bit signed integer. */
|
||||
typedef short int16;
|
||||
|
||||
/** @brief 16-bit unsigned integer. */
|
||||
typedef unsigned short uint16;
|
||||
|
||||
/** @brief 32-bit signed integer. */
|
||||
typedef int int32;
|
||||
|
||||
/** @brief 32-bit unsigned integer. */
|
||||
typedef unsigned int uint32;
|
||||
|
||||
/** @brief 64-bit signed integer. */
|
||||
typedef long long int64;
|
||||
|
||||
/** @brief 64-bit unsigned integer. */
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
/**
|
||||
* @brief Unsigned integer to index elements.
|
||||
* The total number of elements for each algorithm must fit into this type.
|
||||
*/
|
||||
typedef uint64 sequence_index_t;
|
||||
|
||||
/**
|
||||
* @brief Unsigned integer to index a thread number.
|
||||
* The maximum thread number (for each processor) must fit into this type.
|
||||
*/
|
||||
typedef uint16 thread_index_t;
|
||||
|
||||
/**
|
||||
* @brief Longest compare-and-swappable integer type on this platform.
|
||||
*/
|
||||
typedef int64 lcas_t;
|
||||
|
||||
/**
|
||||
* @brief Number of bits of ::lcas_t.
|
||||
*/
|
||||
static const int lcas_t_bits = sizeof(lcas_t) * 8;
|
||||
|
||||
/**
|
||||
* @brief ::lcas_t with the right half of bits set to 1.
|
||||
*/
|
||||
static const lcas_t lcas_t_mask = (((lcas_t)1 << (lcas_t_bits / 2)) - 1);
|
||||
}
|
||||
|
||||
#endif /* _GLIBCXX_TYPES_H */
|
193
libstdc++-v3/include/parallel/unique_copy.h
Normal file
193
libstdc++-v3/include/parallel/unique_copy.h
Normal file
@ -0,0 +1,193 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/unique_copy.h
|
||||
* @brief Parallel implementations of std::unique_copy().
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Robert Geisberger and Robin Dapp.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_UNIQUE_H
|
||||
#define _GLIBCXX_PARALLEL_UNIQUE_H 1
|
||||
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/multiseq_selection.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
|
||||
/** @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.
|
||||
* @param binary_pred Equality predicate.
|
||||
* @return End iterator of result sequence. */
|
||||
template<typename InputIterator, class OutputIterator, class BinaryPredicate>
|
||||
inline OutputIterator
|
||||
parallel_unique_copy(InputIterator first, InputIterator last,
|
||||
OutputIterator result, BinaryPredicate binary_pred)
|
||||
{
|
||||
_GLIBCXX_CALL(last - first)
|
||||
|
||||
typedef std::iterator_traits<InputIterator> traits_type;
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
difference_type size = last - first;
|
||||
int num_threads = __gnu_parallel::get_max_threads();
|
||||
difference_type counter[num_threads + 1];
|
||||
|
||||
if (size == 0)
|
||||
return result;
|
||||
|
||||
// Let the first thread process two parts.
|
||||
difference_type borders[num_threads + 2];
|
||||
__gnu_parallel::equally_split(size, num_threads + 1, borders);
|
||||
|
||||
// First part contains at least one element.
|
||||
#pragma omp parallel num_threads(num_threads)
|
||||
{
|
||||
int iam = omp_get_thread_num();
|
||||
|
||||
difference_type begin, end;
|
||||
|
||||
// Check for length without duplicates
|
||||
// Needed for position in output
|
||||
difference_type i = 0;
|
||||
OutputIterator out = result;
|
||||
if (iam == 0)
|
||||
{
|
||||
begin = borders[0] + 1; // == 1
|
||||
end = borders[iam + 1];
|
||||
|
||||
i++;
|
||||
new (static_cast<void *>(&*out)) value_type(*first);
|
||||
out++;
|
||||
|
||||
for (InputIterator iter = first + begin; iter < first + end; ++iter)
|
||||
{
|
||||
if (!binary_pred(*iter, *(iter-1)))
|
||||
{
|
||||
i++;
|
||||
new (static_cast<void *>(&*out)) value_type(*iter);
|
||||
out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
begin = borders[iam]; //one part
|
||||
end = borders[iam + 1];
|
||||
|
||||
for (InputIterator iter = first + begin; iter < first + end; ++iter)
|
||||
{
|
||||
if (!binary_pred(*iter, *(iter-1)))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
counter[iam] = i;
|
||||
|
||||
// Last part still untouched.
|
||||
difference_type 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 (InputIterator iter = first + begin; iter < first + end; ++iter)
|
||||
{
|
||||
if (iter == first || !binary_pred(*iter, *(iter-1)))
|
||||
{
|
||||
i++;
|
||||
new (static_cast<void *>(&*iter_out)) value_type(*iter);
|
||||
iter_out++;
|
||||
}
|
||||
}
|
||||
|
||||
counter[num_threads] = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int t = 0; t < iam; t++)
|
||||
begin_output += counter[t];
|
||||
|
||||
OutputIterator iter_out = result + begin_output;
|
||||
for (InputIterator iter = first + begin; iter < first + end; ++iter)
|
||||
{
|
||||
if (!binary_pred(*iter, *(iter-1)))
|
||||
{
|
||||
new (static_cast<void *> (&*iter_out)) value_type(*iter);
|
||||
iter_out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
difference_type end_output = 0;
|
||||
for (int t = 0; t < num_threads + 1; t++)
|
||||
end_output += counter[t];
|
||||
|
||||
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 InputIterator, class OutputIterator>
|
||||
inline OutputIterator
|
||||
parallel_unique_copy(InputIterator first, InputIterator last,
|
||||
OutputIterator result)
|
||||
{
|
||||
typedef typename std::iterator_traits<InputIterator>::value_type value_type;
|
||||
|
||||
return parallel_unique_copy(first, last, result, std::equal_to<value_type>());
|
||||
}
|
||||
|
||||
}//namespace __gnu_parallel
|
||||
|
||||
#endif
|
289
libstdc++-v3/include/parallel/workstealing.h
Normal file
289
libstdc++-v3/include/parallel/workstealing.h
Normal file
@ -0,0 +1,289 @@
|
||||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this library; see the file COPYING. If not, write to
|
||||
// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
|
||||
// MA 02111-1307, USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free
|
||||
// software library without restriction. Specifically, if other files
|
||||
// instantiate templates or use macros or inline functions from this
|
||||
// file, or you compile this file and link it with other files to
|
||||
// produce an executable, this file does not by itself cause the
|
||||
// resulting executable to be covered by the GNU General Public
|
||||
// License. This exception does not however invalidate any other
|
||||
// reasons why the executable file might be covered by the GNU General
|
||||
// Public License.
|
||||
|
||||
/** @file parallel/workstealing.h
|
||||
* @brief Parallelization of embarrassingly parallel execution by
|
||||
* means of work-stealing.
|
||||
* This file is a GNU parallel extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
// Written by Felix Putze.
|
||||
|
||||
#ifndef _GLIBCXX_PARALLEL_WORKSTEALING_H
|
||||
#define _GLIBCXX_PARALLEL_WORKSTEALING_H 1
|
||||
|
||||
#include <parallel/parallel.h>
|
||||
#include <parallel/random_number.h>
|
||||
#include <parallel/compatibility.h>
|
||||
|
||||
namespace __gnu_parallel
|
||||
{
|
||||
|
||||
#define _GLIBCXX_JOB_VOLATILE volatile
|
||||
|
||||
/** @brief One job for a certain thread. */
|
||||
template<typename _DifferenceTp>
|
||||
struct Job
|
||||
{
|
||||
typedef _DifferenceTp difference_type;
|
||||
|
||||
/** @brief First element.
|
||||
*
|
||||
* Changed by owning and stealing thread. By stealing thread,
|
||||
* always incremented. */
|
||||
_GLIBCXX_JOB_VOLATILE difference_type first;
|
||||
|
||||
/** @brief Last element.
|
||||
*
|
||||
* Changed by owning thread only. */
|
||||
_GLIBCXX_JOB_VOLATILE difference_type last;
|
||||
|
||||
/** @brief Number of elements, i. e. @c last-first+1.
|
||||
*
|
||||
* Changed by owning thread only. */
|
||||
_GLIBCXX_JOB_VOLATILE difference_type 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 RandomAccessIterator, typename Op, typename Fu, typename Red, typename Result>
|
||||
Op
|
||||
for_each_template_random_access_workstealing(RandomAccessIterator begin,
|
||||
RandomAccessIterator end,
|
||||
Op op, Fu& f, Red r,
|
||||
Result base, Result& output,
|
||||
typename std::iterator_traits<RandomAccessIterator>::difference_type bound)
|
||||
{
|
||||
_GLIBCXX_CALL(end - begin)
|
||||
|
||||
typedef std::iterator_traits<RandomAccessIterator> traits_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
|
||||
difference_type chunk_size = static_cast<difference_type>(Settings::workstealing_chunk_size);
|
||||
|
||||
// How many jobs?
|
||||
difference_type length = (bound < 0) ? (end - begin) : bound;
|
||||
|
||||
// To avoid false sharing in a cache line.
|
||||
const int stride = Settings::cache_line_size * 10 / sizeof(Job<difference_type>) + 1;
|
||||
|
||||
// Total number of threads currently working.
|
||||
thread_index_t busy = 0;
|
||||
thread_index_t num_threads = get_max_threads();
|
||||
difference_type num_threads_min = num_threads < end - begin ? num_threads : end - begin;
|
||||
|
||||
// No more threads than jobs, at least one thread.
|
||||
difference_type num_threads_max = num_threads_min > 1 ? num_threads_min : 1;
|
||||
num_threads = static_cast<thread_index_t>(num_threads_max);
|
||||
|
||||
// Create job description array.
|
||||
Job<difference_type> *job = new Job<difference_type>[num_threads * stride];
|
||||
|
||||
// Write base value to output.
|
||||
output = base;
|
||||
|
||||
#pragma omp parallel shared(busy) num_threads(num_threads)
|
||||
{
|
||||
// Initialization phase.
|
||||
|
||||
// Flags for every thread if it is doing productive work.
|
||||
bool iam_working = false;
|
||||
|
||||
// Thread id.
|
||||
thread_index_t iam = omp_get_thread_num();
|
||||
|
||||
// This job.
|
||||
Job<difference_type>& my_job = job[iam * stride];
|
||||
|
||||
// Random number (for work stealing).
|
||||
thread_index_t victim;
|
||||
|
||||
// Local value for reduction.
|
||||
Result result = Result();
|
||||
|
||||
// Number of elements to steal in one attempt.
|
||||
difference_type steal;
|
||||
|
||||
// Every thread has its own random number generator (modulo num_threads).
|
||||
random_number rand_gen(iam, num_threads);
|
||||
|
||||
#pragma omp atomic
|
||||
// This thread is currently working.
|
||||
busy++;
|
||||
|
||||
iam_working = true;
|
||||
|
||||
// How many jobs per thread? last thread gets the rest.
|
||||
my_job.first = static_cast<difference_type>(iam * (length / num_threads));
|
||||
|
||||
my_job.last = (iam == (num_threads - 1)) ? (length - 1) : ((iam + 1) * (length / num_threads) - 1);
|
||||
my_job.load = my_job.last - my_job.first + 1;
|
||||
|
||||
// Init result with first value (to have a base value for reduction).
|
||||
if (my_job.first <= my_job.last)
|
||||
{
|
||||
// Cannot use volatile variable directly.
|
||||
difference_type my_first = my_job.first;
|
||||
result = f(op, begin + my_first);
|
||||
my_job.first++;
|
||||
my_job.load--;
|
||||
}
|
||||
|
||||
RandomAccessIterator current;
|
||||
|
||||
#pragma omp barrier
|
||||
|
||||
// Actual work phase
|
||||
// Work on own or stolen start
|
||||
while (busy > 0)
|
||||
{
|
||||
// Work until no productive thread left.
|
||||
#pragma omp flush(busy)
|
||||
|
||||
// Thread has own work to do
|
||||
while (my_job.first <= my_job.last)
|
||||
{
|
||||
// fetch-and-add call
|
||||
// Reserve current job block (size chunk_size) in my queue.
|
||||
difference_type current_job = fetch_and_add<difference_type>(&(my_job.first), chunk_size);
|
||||
|
||||
// Update load, to make the three values consistent,
|
||||
// first might have been changed in the meantime
|
||||
my_job.load = my_job.last - my_job.first + 1;
|
||||
for (difference_type job_counter = 0; job_counter < chunk_size && current_job <= my_job.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)
|
||||
{
|
||||
#pragma omp atomic
|
||||
// This thread no longer has work.
|
||||
busy--;
|
||||
|
||||
iam_working = false;
|
||||
}
|
||||
|
||||
difference_type supposed_first, supposed_last, supposed_load;
|
||||
do
|
||||
{
|
||||
// Find random nonempty deque (not own) and do consistency check.
|
||||
yield();
|
||||
#pragma omp flush(busy)
|
||||
victim = rand_gen();
|
||||
supposed_first = job[victim * stride].first;
|
||||
supposed_last = job[victim * stride].last;
|
||||
supposed_load = job[victim * stride].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;
|
||||
|
||||
// Protects against stealing threads
|
||||
// omp_set_lock(&(job[victim * stride].lock));
|
||||
|
||||
// Push victim's start forward.
|
||||
difference_type stolen_first = fetch_and_add<difference_type>(&(job[victim * stride].first), steal);
|
||||
difference_type stolen_try = stolen_first + steal - difference_type(1);
|
||||
|
||||
// Protects against working thread
|
||||
// omp_unset_lock(&(job[victim * stride].lock));
|
||||
|
||||
my_job.first = stolen_first;
|
||||
|
||||
// Avoid std::min dependencies.
|
||||
my_job.last = stolen_try < supposed_last ? stolen_try : supposed_last;
|
||||
|
||||
my_job.load = my_job.last - my_job.first + 1;
|
||||
|
||||
//omp_unset_lock(&(my_job.lock));
|
||||
|
||||
#pragma omp atomic
|
||||
// Has potential work again.
|
||||
busy++;
|
||||
iam_working = true;
|
||||
|
||||
#pragma omp flush(busy)
|
||||
}
|
||||
#pragma omp flush(busy)
|
||||
} // end while busy > 0
|
||||
#pragma omp critical(writeOutput)
|
||||
// Add accumulated result to output.
|
||||
output = r(output, result);
|
||||
|
||||
//omp_destroy_lock(&(my_job.lock));
|
||||
}
|
||||
|
||||
delete[] job;
|
||||
|
||||
// Points to last element processed (needed as return value for
|
||||
// some algorithms like transform)
|
||||
f.finish_iterator = begin + length;
|
||||
|
||||
return op;
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
#endif
|
@ -66,4 +66,8 @@
|
||||
#include <bits/stl_algobase.h>
|
||||
#include <bits/stl_algo.h>
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# include <parallel/algorithm>
|
||||
#endif
|
||||
|
||||
#endif /* _GLIBCXX_ALGORITHM */
|
||||
|
@ -62,7 +62,7 @@
|
||||
((__n) < 1 ? 0 : ((__n) + _GLIBCXX_BITSET_BITS_PER_WORD - 1) \
|
||||
/ _GLIBCXX_BITSET_BITS_PER_WORD)
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
/**
|
||||
* @if maint
|
||||
|
@ -67,4 +67,8 @@
|
||||
#include <bits/stl_iterator_base_types.h>
|
||||
#include <bits/stl_numeric.h>
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# include <parallel/numeric>
|
||||
#endif
|
||||
|
||||
#endif /* _GLIBCXX_NUMERIC */
|
||||
|
@ -49,8 +49,12 @@
|
||||
#include <bits/cpp_type_traits.h>
|
||||
#include <bits/localefwd.h> // For operators >>, <<, and getline.
|
||||
#include <bits/ostream_insert.h>
|
||||
#include <bits/stl_iterator_base_types.h>
|
||||
#include <bits/stl_iterator_base_funcs.h>
|
||||
#include <bits/stl_iterator.h>
|
||||
#include <bits/stl_function.h> // For less
|
||||
#include <ext/numeric_traits.h>
|
||||
#include <bits/stl_algobase.h>
|
||||
#include <bits/basic_string.h>
|
||||
|
||||
#ifndef _GLIBCXX_EXPORT_TEMPLATE
|
||||
|
@ -86,6 +86,7 @@ AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@
|
||||
ATOMIC_FLAGS = @ATOMIC_FLAGS@
|
||||
ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
@ -123,6 +124,8 @@ ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_PARALLEL_FALSE = @ENABLE_PARALLEL_FALSE@
|
||||
ENABLE_PARALLEL_TRUE = @ENABLE_PARALLEL_TRUE@
|
||||
ENABLE_SYMVERS_DARWIN_FALSE = @ENABLE_SYMVERS_DARWIN_FALSE@
|
||||
ENABLE_SYMVERS_DARWIN_TRUE = @ENABLE_SYMVERS_DARWIN_TRUE@
|
||||
ENABLE_SYMVERS_FALSE = @ENABLE_SYMVERS_FALSE@
|
||||
|
@ -141,6 +141,7 @@ AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@
|
||||
ATOMIC_FLAGS = @ATOMIC_FLAGS@
|
||||
ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
@ -178,6 +179,8 @@ ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_PARALLEL_FALSE = @ENABLE_PARALLEL_FALSE@
|
||||
ENABLE_PARALLEL_TRUE = @ENABLE_PARALLEL_TRUE@
|
||||
ENABLE_SYMVERS_DARWIN_FALSE = @ENABLE_SYMVERS_DARWIN_FALSE@
|
||||
ENABLE_SYMVERS_DARWIN_TRUE = @ENABLE_SYMVERS_DARWIN_TRUE@
|
||||
ENABLE_SYMVERS_FALSE = @ENABLE_SYMVERS_FALSE@
|
||||
|
@ -71,6 +71,7 @@ AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@
|
||||
ATOMIC_FLAGS = @ATOMIC_FLAGS@
|
||||
ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
@ -108,6 +109,8 @@ ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_PARALLEL_FALSE = @ENABLE_PARALLEL_FALSE@
|
||||
ENABLE_PARALLEL_TRUE = @ENABLE_PARALLEL_TRUE@
|
||||
ENABLE_SYMVERS_DARWIN_FALSE = @ENABLE_SYMVERS_DARWIN_FALSE@
|
||||
ENABLE_SYMVERS_DARWIN_TRUE = @ENABLE_SYMVERS_DARWIN_TRUE@
|
||||
ENABLE_SYMVERS_FALSE = @ENABLE_SYMVERS_FALSE@
|
||||
|
@ -32,10 +32,12 @@ SH_FLAG="-Wl,--rpath -Wl,$BUILD_DIR/../../gcc \
|
||||
-Wl,--rpath -Wl,$BUILD_DIR/src/.libs"
|
||||
ST_FLAG="-static"
|
||||
LINK=$SH_FLAG
|
||||
CXX="$COMPILER $INCLUDES $PCH_FLAGS $FLAGS $LINK"
|
||||
CXX="$COMPILER $INCLUDES $FLAGS $CXXFLAGS $LINK"
|
||||
LIBS="./libtestc++.a"
|
||||
TESTS_FILE="testsuite_files_performance"
|
||||
|
||||
echo CXX is $CXX
|
||||
|
||||
for NAME in `cat $TESTS_FILE`
|
||||
do
|
||||
RUN=true
|
||||
@ -79,7 +81,7 @@ do
|
||||
EXE_NAME="`echo $FILE_NAME.exe`"
|
||||
$CXX $TESTNAME $LIBS -o $EXE_NAME
|
||||
if [ -f $EXE_NAME ]; then
|
||||
./$EXE_NAME >& tmp.$FILE_NAME
|
||||
./$EXE_NAME >& tmp.$FILE_NAME
|
||||
else
|
||||
echo "compile error:"
|
||||
echo "$CXX $TESTNAME $LIBS -o $EXE_NAME"
|
||||
|
@ -58,6 +58,13 @@ case ${query} in
|
||||
CXXFLAGS_config="@SECTION_FLAGS@ @CXXFLAGS@ @EXTRA_CXX_FLAGS@"
|
||||
echo ${CXXFLAGS_default} ${CXXFLAGS_config}
|
||||
;;
|
||||
--cxxparallelflags)
|
||||
CXXFLAGS_parallel="-D_GLIBCXX_PARALLEL -fopenmp
|
||||
-B${BUILD_DIR}/../libgomp
|
||||
-I${BUILD_DIR}/../libgomp
|
||||
-L${BUILD_DIR}/../libgomp/.libs -lgomp"
|
||||
echo ${CXXFLAGS_parallel}
|
||||
;;
|
||||
--cxxpchflags)
|
||||
PCHFLAGS="@glibcxx_PCHFLAGS@"
|
||||
echo ${PCHFLAGS}
|
||||
|
@ -112,8 +112,7 @@ atomicity.cc: ${atomicity_file}
|
||||
# Source files linked in via configuration/make substitution for a
|
||||
# particular host, but with ad hoc naming rules.
|
||||
host_sources_extra = \
|
||||
basic_file.cc \
|
||||
c++locale.cc
|
||||
basic_file.cc c++locale.cc ${ldbl_compat_sources} ${parallel_sources}
|
||||
|
||||
c++locale.cc: ${glibcxx_srcdir}/$(CLOCALE_CC)
|
||||
$(LN_S) ${glibcxx_srcdir}/$(CLOCALE_CC) ./$@ || true
|
||||
@ -121,6 +120,12 @@ c++locale.cc: ${glibcxx_srcdir}/$(CLOCALE_CC)
|
||||
basic_file.cc: ${glibcxx_srcdir}/$(BASIC_FILE_CC)
|
||||
$(LN_S) ${glibcxx_srcdir}/$(BASIC_FILE_CC) ./$@ || true
|
||||
|
||||
if ENABLE_PARALLEL
|
||||
parallel_sources = parallel_list.cc
|
||||
else
|
||||
parallel_sources =
|
||||
endif
|
||||
|
||||
if GLIBCXX_LDBL_COMPAT
|
||||
ldbl_compat_sources = compatibility-ldbl.cc
|
||||
else
|
||||
@ -137,7 +142,6 @@ sources = \
|
||||
complex_io.cc \
|
||||
ctype.cc \
|
||||
debug.cc \
|
||||
debug_list.cc \
|
||||
functexcept.cc \
|
||||
hash.cc \
|
||||
hash_c++0x.cc \
|
||||
@ -148,6 +152,7 @@ sources = \
|
||||
ios_locale.cc \
|
||||
limits.cc \
|
||||
list.cc \
|
||||
debug_list.cc \
|
||||
locale.cc \
|
||||
locale_init.cc \
|
||||
locale_facets.cc \
|
||||
@ -175,8 +180,7 @@ sources = \
|
||||
wlocale-inst.cc \
|
||||
wstring-inst.cc \
|
||||
${host_sources} \
|
||||
${host_sources_extra} \
|
||||
${ldbl_compat_sources}
|
||||
${host_sources_extra}
|
||||
|
||||
VPATH = $(top_srcdir)/src:$(top_srcdir)
|
||||
|
||||
@ -207,6 +211,12 @@ concept-inst.lo: concept-inst.cc
|
||||
concept-inst.o: concept-inst.cc
|
||||
$(CXXCOMPILE) -D_GLIBCXX_CONCEPT_CHECKS -fimplicit-templates -c $<
|
||||
|
||||
# Use special rules for parallel_list.cc compile.
|
||||
parallel_list.lo: parallel_list.cc
|
||||
$(LTCXXCOMPILE) -I$(glibcxx_builddir)/../libgomp -c $<
|
||||
parallel_list.o: parallel_list.cc
|
||||
$(CXXCOMPILE) -I$(glibcxx_builddir)/../libgomp -c $<
|
||||
|
||||
# Use special rules for the C++0x sources so that the proper flags are passed.
|
||||
system_error.lo: system_error.cc
|
||||
$(LTCXXCOMPILE) -std=gnu++0x -c $<
|
||||
|
@ -69,9 +69,9 @@ toolexeclibLTLIBRARIES_INSTALL = $(INSTALL)
|
||||
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
|
||||
am__libstdc___la_SOURCES_DIST = bitmap_allocator.cc pool_allocator.cc \
|
||||
mt_allocator.cc codecvt.cc compatibility.cc complex_io.cc \
|
||||
ctype.cc debug.cc debug_list.cc functexcept.cc hash.cc \
|
||||
hash_c++0x.cc globals_io.cc ios.cc ios_failure.cc ios_init.cc \
|
||||
ios_locale.cc limits.cc list.cc locale.cc locale_init.cc \
|
||||
ctype.cc debug.cc functexcept.cc hash.cc hash_c++0x.cc \
|
||||
globals_io.cc ios.cc ios_failure.cc ios_init.cc ios_locale.cc \
|
||||
limits.cc list.cc debug_list.cc locale.cc locale_init.cc \
|
||||
locale_facets.cc localename.cc stdexcept.cc strstream.cc \
|
||||
system_error.cc tree.cc allocator-inst.cc concept-inst.cc \
|
||||
fstream-inst.cc ext-inst.cc ios-inst.cc iostream-inst.cc \
|
||||
@ -81,25 +81,28 @@ am__libstdc___la_SOURCES_DIST = bitmap_allocator.cc pool_allocator.cc \
|
||||
wstring-inst.cc atomicity.cc codecvt_members.cc \
|
||||
collate_members.cc ctype_members.cc messages_members.cc \
|
||||
monetary_members.cc numeric_members.cc time_members.cc \
|
||||
basic_file.cc c++locale.cc compatibility-ldbl.cc
|
||||
basic_file.cc c++locale.cc compatibility-ldbl.cc \
|
||||
parallel_list.cc
|
||||
am__objects_1 = atomicity.lo codecvt_members.lo collate_members.lo \
|
||||
ctype_members.lo messages_members.lo monetary_members.lo \
|
||||
numeric_members.lo time_members.lo
|
||||
am__objects_2 = basic_file.lo c++locale.lo
|
||||
@GLIBCXX_LDBL_COMPAT_TRUE@am__objects_3 = compatibility-ldbl.lo
|
||||
am__objects_4 = bitmap_allocator.lo pool_allocator.lo mt_allocator.lo \
|
||||
@GLIBCXX_LDBL_COMPAT_TRUE@am__objects_2 = compatibility-ldbl.lo
|
||||
@ENABLE_PARALLEL_TRUE@am__objects_3 = parallel_list.lo
|
||||
am__objects_4 = basic_file.lo c++locale.lo $(am__objects_2) \
|
||||
$(am__objects_3)
|
||||
am__objects_5 = bitmap_allocator.lo pool_allocator.lo mt_allocator.lo \
|
||||
codecvt.lo compatibility.lo complex_io.lo ctype.lo debug.lo \
|
||||
debug_list.lo functexcept.lo hash.lo hash_c++0x.lo \
|
||||
globals_io.lo ios.lo ios_failure.lo ios_init.lo ios_locale.lo \
|
||||
limits.lo list.lo locale.lo locale_init.lo locale_facets.lo \
|
||||
functexcept.lo hash.lo hash_c++0x.lo globals_io.lo ios.lo \
|
||||
ios_failure.lo ios_init.lo ios_locale.lo limits.lo list.lo \
|
||||
debug_list.lo locale.lo locale_init.lo locale_facets.lo \
|
||||
localename.lo stdexcept.lo strstream.lo system_error.lo \
|
||||
tree.lo allocator-inst.lo concept-inst.lo fstream-inst.lo \
|
||||
ext-inst.lo ios-inst.lo iostream-inst.lo istream-inst.lo \
|
||||
istream.lo locale-inst.lo misc-inst.lo ostream-inst.lo \
|
||||
sstream-inst.lo streambuf-inst.lo streambuf.lo string-inst.lo \
|
||||
valarray-inst.lo wlocale-inst.lo wstring-inst.lo \
|
||||
$(am__objects_1) $(am__objects_2) $(am__objects_3)
|
||||
am_libstdc___la_OBJECTS = $(am__objects_4)
|
||||
$(am__objects_1) $(am__objects_4)
|
||||
am_libstdc___la_OBJECTS = $(am__objects_5)
|
||||
libstdc___la_OBJECTS = $(am_libstdc___la_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp =
|
||||
@ -121,6 +124,7 @@ AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@
|
||||
ATOMIC_FLAGS = @ATOMIC_FLAGS@
|
||||
ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
@ -158,6 +162,8 @@ ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_PARALLEL_FALSE = @ENABLE_PARALLEL_FALSE@
|
||||
ENABLE_PARALLEL_TRUE = @ENABLE_PARALLEL_TRUE@
|
||||
ENABLE_SYMVERS_DARWIN_FALSE = @ENABLE_SYMVERS_DARWIN_FALSE@
|
||||
ENABLE_SYMVERS_DARWIN_TRUE = @ENABLE_SYMVERS_DARWIN_TRUE@
|
||||
ENABLE_SYMVERS_FALSE = @ENABLE_SYMVERS_FALSE@
|
||||
@ -348,9 +354,10 @@ atomicity_file = ${glibcxx_srcdir}/$(ATOMICITY_SRCDIR)/atomicity.h
|
||||
# Source files linked in via configuration/make substitution for a
|
||||
# particular host, but with ad hoc naming rules.
|
||||
host_sources_extra = \
|
||||
basic_file.cc \
|
||||
c++locale.cc
|
||||
basic_file.cc c++locale.cc ${ldbl_compat_sources} ${parallel_sources}
|
||||
|
||||
@ENABLE_PARALLEL_FALSE@parallel_sources =
|
||||
@ENABLE_PARALLEL_TRUE@parallel_sources = parallel_list.cc
|
||||
@GLIBCXX_LDBL_COMPAT_FALSE@ldbl_compat_sources =
|
||||
@GLIBCXX_LDBL_COMPAT_TRUE@ldbl_compat_sources = compatibility-ldbl.cc
|
||||
|
||||
@ -364,7 +371,6 @@ sources = \
|
||||
complex_io.cc \
|
||||
ctype.cc \
|
||||
debug.cc \
|
||||
debug_list.cc \
|
||||
functexcept.cc \
|
||||
hash.cc \
|
||||
hash_c++0x.cc \
|
||||
@ -375,6 +381,7 @@ sources = \
|
||||
ios_locale.cc \
|
||||
limits.cc \
|
||||
list.cc \
|
||||
debug_list.cc \
|
||||
locale.cc \
|
||||
locale_init.cc \
|
||||
locale_facets.cc \
|
||||
@ -402,8 +409,7 @@ sources = \
|
||||
wlocale-inst.cc \
|
||||
wstring-inst.cc \
|
||||
${host_sources} \
|
||||
${host_sources_extra} \
|
||||
${ldbl_compat_sources}
|
||||
${host_sources_extra}
|
||||
|
||||
libstdc___la_SOURCES = $(sources)
|
||||
libstdc___la_LIBADD = \
|
||||
@ -790,6 +796,12 @@ concept-inst.lo: concept-inst.cc
|
||||
concept-inst.o: concept-inst.cc
|
||||
$(CXXCOMPILE) -D_GLIBCXX_CONCEPT_CHECKS -fimplicit-templates -c $<
|
||||
|
||||
# Use special rules for parallel_list.cc compile.
|
||||
parallel_list.lo: parallel_list.cc
|
||||
$(LTCXXCOMPILE) -I$(glibcxx_builddir)/../libgomp -c $<
|
||||
parallel_list.o: parallel_list.cc
|
||||
$(CXXCOMPILE) -I$(glibcxx_builddir)/../libgomp -c $<
|
||||
|
||||
# Use special rules for the C++0x sources so that the proper flags are passed.
|
||||
system_error.lo: system_error.cc
|
||||
$(LTCXXCOMPILE) -std=gnu++0x -c $<
|
||||
|
@ -55,7 +55,7 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
|
||||
_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
||||
|
||||
void
|
||||
_List_node_base::swap(_List_node_base& __x, _List_node_base& __y)
|
||||
|
32
libstdc++-v3/src/parallel_list.cc
Normal file
32
libstdc++-v3/src/parallel_list.cc
Normal file
@ -0,0 +1,32 @@
|
||||
// Parallel mode support code for list -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007 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 2, 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING. If not, write to the Free
|
||||
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
// USA.
|
||||
|
||||
// As a special exception, you may use this file as part of a free software
|
||||
// library without restriction. Specifically, if other files instantiate
|
||||
// templates or use macros or inline functions from this file, or you compile
|
||||
// this file and link it with other files to produce an executable, this
|
||||
// file does not by itself cause the resulting executable to be covered by
|
||||
// the GNU General Public License. This exception does not however
|
||||
// invalidate any other reasons why the executable file might be covered by
|
||||
// the GNU General Public License.
|
||||
|
||||
#define _GLIBCXX_PARALLEL
|
||||
|
||||
#include "list.cc"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user