passenger 5.1.4 → 5.1.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.editorconfig +9 -0
- data/CHANGELOG +9 -0
- data/build/cxx_tests.rb +11 -1
- data/build/documentation.rb +0 -32
- data/build/support/cxx_dependency_map.rb +602 -2
- data/build/test_basics.rb +3 -3
- data/dev/boost-patches/0001-Patch-boost-thread-so-that-oxt-thread-can-use-it.patch +48 -0
- data/dev/boost-patches/0002-Make-boost-thread_interrupted-derive-from-oxt-tracab.patch +33 -0
- data/dev/boost-patches/0003-Disable-a-Clang-pragma-to-prevent-warnings-on-OS-X.patch +25 -0
- data/dev/ci/README.md +121 -0
- data/dev/ci/lib/functions.sh +129 -0
- data/dev/ci/lib/set-container-envvars.sh +46 -0
- data/dev/ci/lib/setup-container.sh +43 -0
- data/dev/ci/run-tests-natively +24 -0
- data/dev/ci/run-tests-with-docker +42 -0
- data/dev/ci/scripts/debug-console-wrapper.sh +27 -0
- data/dev/ci/scripts/docker-entrypoint-stage2.sh +17 -0
- data/dev/ci/scripts/docker-entrypoint.sh +17 -0
- data/dev/ci/scripts/inituidgid +17 -0
- data/dev/ci/scripts/run-tests-natively-stage2.sh +17 -0
- data/dev/ci/scripts/setup-host-natively.sh +11 -0
- data/dev/ci/setup-host +50 -0
- data/dev/ci/tests/apache2/run +6 -0
- data/dev/ci/tests/apache2/setup +4 -0
- data/dev/ci/tests/cxx/run +9 -0
- data/dev/ci/tests/cxx/setup +4 -0
- data/dev/ci/tests/nginx-dynamic/run +20 -0
- data/dev/ci/tests/nginx-dynamic/setup +4 -0
- data/dev/ci/tests/nginx/run +5 -0
- data/dev/ci/tests/nginx/setup +4 -0
- data/dev/ci/tests/nodejs/run +4 -0
- data/dev/ci/tests/nodejs/setup +4 -0
- data/dev/ci/tests/ruby/run +4 -0
- data/dev/ci/tests/ruby/setup +4 -0
- data/dev/ci/tests/source-packaging/run +4 -0
- data/dev/ci/tests/source-packaging/setup +4 -0
- data/dev/ci/tests/standalone/run +4 -0
- data/dev/ci/tests/standalone/setup +4 -0
- data/dev/copy_boost_headers +8 -2
- data/src/agent/Core/ApiServer.h +11 -5
- data/src/agent/Core/Controller.h +12 -46
- data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
- data/src/agent/Core/Controller/Config.h +369 -0
- data/src/agent/Core/Controller/ForwardResponse.cpp +4 -4
- data/src/agent/Core/Controller/Hooks.cpp +15 -3
- data/src/agent/Core/Controller/Implementation.cpp +1 -1
- data/src/agent/Core/Controller/InitRequest.cpp +28 -39
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +25 -60
- data/src/agent/Core/Controller/InternalUtils.cpp +0 -16
- data/src/agent/Core/Controller/Miscellaneous.cpp +0 -17
- data/src/agent/Core/Controller/Request.h +2 -0
- data/src/agent/Core/Controller/SendRequest.cpp +4 -4
- data/src/agent/Core/Controller/{StateInspectionAndConfiguration.cpp → StateInspection.cpp} +0 -22
- data/src/agent/Core/Controller/TurboCaching.h +11 -10
- data/src/agent/Core/CoreMain.cpp +16 -6
- data/src/agent/Core/ResponseCache.h +3 -3
- data/src/agent/Core/SpawningKit/SmartSpawner.h +9 -3
- data/src/agent/Core/SpawningKit/Spawner.h +7 -3
- data/src/agent/UstRouter/ApiServer.h +3 -2
- data/src/agent/UstRouter/Controller.h +66 -32
- data/src/agent/UstRouter/UstRouterMain.cpp +10 -2
- data/src/agent/Watchdog/ApiServer.h +3 -2
- data/src/agent/Watchdog/WatchdogMain.cpp +3 -1
- data/src/apache2_module/ConfigurationCommands.cpp +1 -1
- data/src/cxx_supportlib/ConfigKit/Common.h +125 -0
- data/src/cxx_supportlib/ConfigKit/ConfigKit.h +34 -0
- data/src/cxx_supportlib/ConfigKit/README.md +895 -0
- data/src/cxx_supportlib/ConfigKit/Schema.h +331 -0
- data/src/cxx_supportlib/ConfigKit/Store.h +385 -0
- data/src/cxx_supportlib/ConfigKit/TableTranslator.h +185 -0
- data/src/cxx_supportlib/ConfigKit/Utils.h +141 -0
- data/src/cxx_supportlib/ConfigKit/VariantMapUtils.h +81 -0
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/Crypto.cpp +2 -2
- data/src/cxx_supportlib/Logging.h +0 -35
- data/src/cxx_supportlib/ServerKit/HttpServer.h +35 -16
- data/src/cxx_supportlib/ServerKit/Server.h +65 -25
- data/src/cxx_supportlib/oxt/macros.hpp +3 -0
- data/src/cxx_supportlib/vendor-modified/boost/algorithm/string/replace.hpp +0 -2
- data/src/cxx_supportlib/vendor-modified/boost/array.hpp +53 -42
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/atomic_template.hpp +11 -5
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/bitwise_cast.hpp +13 -2
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/caps_gcc_x86.hpp +23 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/caps_msvc_x86.hpp +5 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/config.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/interlocked.hpp +8 -1
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_emulated.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_alpha.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_arm.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_atomic.hpp +5 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_ppc.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_sparc.hpp +6 -4
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_sync.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_x86.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_x86_dcas.hpp +28 -17
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_linux_arm.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_msvc_arm.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_msvc_x86.hpp +9 -4
- data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/platform.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/bind/arg.hpp +10 -3
- data/src/cxx_supportlib/vendor-modified/boost/bind/bind.hpp +90 -18
- data/src/cxx_supportlib/vendor-modified/boost/cerrno.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/chrono/duration.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/auto_link.hpp +8 -3
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/borland.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/clang.hpp +35 -6
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/codegear.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/comeau.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/common_edg.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/compaq_cxx.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/cray.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/digitalmars.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/gcc.hpp +19 -4
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/gcc_xml.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/greenhills.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/hp_acc.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/intel.hpp +29 -7
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/kai.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/metrowerks.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/mpw.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/nvcc.hpp +16 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/pathscale.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/pgi.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/sgi_mipspro.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/sunpro_cc.hpp +10 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/vacpp.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/visualc.hpp +44 -16
- data/src/cxx_supportlib/vendor-modified/boost/config/compiler/xlcpp.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/platform/cygwin.hpp +1 -2
- data/src/cxx_supportlib/vendor-modified/boost/config/platform/linux.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/select_compiler_config.hpp +21 -21
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/dinkumware.hpp +42 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libcomo.hpp +7 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libcpp.hpp +40 -7
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libstdcpp3.hpp +39 -6
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/modena.hpp +7 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/msl.hpp +7 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/roguewave.hpp +7 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/sgi.hpp +8 -1
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/stlport.hpp +7 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/vacpp.hpp +7 -0
- data/src/cxx_supportlib/vendor-modified/boost/config/suffix.hpp +33 -4
- data/src/cxx_supportlib/vendor-modified/boost/container/adaptive_pool.hpp +0 -2
- data/src/cxx_supportlib/vendor-modified/boost/container/allocator.hpp +0 -3
- data/src/cxx_supportlib/vendor-modified/boost/container/allocator_traits.hpp +34 -27
- data/src/cxx_supportlib/vendor-modified/boost/container/deque.hpp +62 -26
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/addressof.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/advanced_insert_int.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/compare_functors.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/config_begin.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/construct_in_place.hpp +39 -5
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/copy_move_algo.hpp +49 -32
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/dispatch_uses_allocator.hpp +175 -7
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/flat_tree.hpp +223 -98
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/is_sorted.hpp +57 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/iterators.hpp +88 -41
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/mpl.hpp +7 -8
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/mutex.hpp +4 -9
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/node_alloc_holder.hpp +45 -18
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/pair.hpp +205 -26
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/tree.hpp +290 -181
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/value_init.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/variadic_templates_tools.hpp +24 -19
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/workaround.hpp +38 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/flat_map.hpp +320 -46
- data/src/cxx_supportlib/vendor-modified/boost/container/flat_set.hpp +91 -18
- data/src/cxx_supportlib/vendor-modified/boost/container/list.hpp +23 -19
- data/src/cxx_supportlib/vendor-modified/boost/container/map.hpp +491 -120
- data/src/cxx_supportlib/vendor-modified/boost/container/new_allocator.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/container/node_allocator.hpp +0 -3
- data/src/cxx_supportlib/vendor-modified/boost/container/node_handle.hpp +399 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/deque.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/flat_map.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/flat_set.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/list.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/map.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/set.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/slist.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/small_vector.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/stable_vector.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/string.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/pmr/vector.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/set.hpp +101 -20
- data/src/cxx_supportlib/vendor-modified/boost/container/slist.hpp +19 -14
- data/src/cxx_supportlib/vendor-modified/boost/container/small_vector.hpp +117 -59
- data/src/cxx_supportlib/vendor-modified/boost/container/stable_vector.hpp +8 -6
- data/src/cxx_supportlib/vendor-modified/boost/container/static_vector.hpp +33 -28
- data/src/cxx_supportlib/vendor-modified/boost/container/string.hpp +414 -70
- data/src/cxx_supportlib/vendor-modified/boost/container/throw_exception.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/container/uses_allocator_fwd.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/container/vector.hpp +134 -117
- data/src/cxx_supportlib/vendor-modified/boost/core/addressof.hpp +202 -99
- data/src/cxx_supportlib/vendor-modified/boost/core/demangle.hpp +8 -10
- data/src/cxx_supportlib/vendor-modified/boost/core/lightweight_test.hpp +217 -1
- data/src/cxx_supportlib/vendor-modified/boost/core/scoped_enum.hpp +29 -27
- data/src/cxx_supportlib/vendor-modified/boost/current_function.hpp +5 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/c_time.hpp +13 -13
- data/src/cxx_supportlib/vendor-modified/boost/date_time/constrained_value.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/date_time/date.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/date_duration.hpp +4 -3
- data/src/cxx_supportlib/vendor-modified/boost/date_time/date_duration_types.hpp +6 -5
- data/src/cxx_supportlib/vendor-modified/boost/date_time/date_facet.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/date_time/date_names_put.hpp +8 -7
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_calendar.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_date.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_day.hpp +4 -3
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_day_of_year.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_duration.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_duration_types.hpp +4 -3
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_facet.hpp +27 -7
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_month.hpp +5 -5
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_serialize.hpp +5 -0
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_weekday.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_year.hpp +4 -5
- data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian_calendar.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/local_time/local_date_time.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/date_time/local_time/posix_time_zone.hpp +4 -3
- data/src/cxx_supportlib/vendor-modified/boost/date_time/period.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/date_duration_operators.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/posix_time_config.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/posix_time_duration.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/ptime.hpp +6 -5
- data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/time_parsers.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/date_time/time_duration.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/date_time/time_facet.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/date_time/time_zone_base.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/date_time/year_month_day.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/detail/iterator.hpp +13 -0
- data/src/cxx_supportlib/vendor-modified/boost/detail/lcast_precision.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/detail/workaround.hpp +5 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/detail/error_info_impl.hpp +11 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/detail/shared_ptr.hpp +17 -0
- data/src/cxx_supportlib/vendor-modified/boost/exception/exception.hpp +25 -3
- data/src/cxx_supportlib/vendor-modified/boost/exception/get_error_info.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/exception/info.hpp +114 -1
- data/src/cxx_supportlib/vendor-modified/boost/function/function_base.hpp +116 -142
- data/src/cxx_supportlib/vendor-modified/boost/function/function_template.hpp +57 -69
- data/src/cxx_supportlib/vendor-modified/boost/functional/hash/detail/hash_float.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/functional/hash/extensions.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/functional/hash/hash.hpp +27 -13
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/any_hook.hpp +4 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/avl_set.hpp +99 -12
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/avl_set_hook.hpp +4 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/avltree.hpp +35 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/avltree_algorithms.hpp +37 -6
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/bs_set.hpp +95 -8
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/bs_set_hook.hpp +4 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/bstree.hpp +209 -72
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/bstree_algorithms.hpp +86 -20
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/circular_list_algorithms.hpp +11 -11
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/circular_slist_algorithms.hpp +6 -6
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/algo_type.hpp +4 -1
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/any_node_and_algorithms.hpp +58 -45
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/avltree_node.hpp +27 -26
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/bstree_algorithms_base.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/common_slist_algorithms.hpp +7 -7
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/config_begin.hpp +8 -3
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/default_header_holder.hpp +4 -3
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/ebo_functor_holder.hpp +27 -26
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/equal_to_value.hpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/exception_disposer.hpp +4 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/generic_hook.hpp +9 -7
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/has_member_function_callable_with.hpp +83 -57
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/hashtable_node.hpp +30 -30
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/hook_traits.hpp +9 -8
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/iiterator.hpp +8 -7
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/iterator.hpp +16 -15
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/key_nodeptr_comp.hpp +70 -44
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/list_iterator.hpp +22 -21
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/list_node.hpp +7 -6
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/parent_from_member.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/rbtree_node.hpp +29 -28
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/reverse_iterator.hpp +33 -12
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/size_holder.hpp +19 -12
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/slist_iterator.hpp +21 -20
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/slist_node.hpp +4 -3
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/to_raw_pointer.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/transform_iterator.hpp +23 -22
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_iterator.hpp +23 -22
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_node.hpp +10 -9
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_value_compare.hpp +103 -29
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/workaround.hpp +15 -0
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/hashtable.hpp +295 -211
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/linear_slist_algorithms.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/list.hpp +20 -7
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/list_hook.hpp +4 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/member_value_traits.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/options.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/parent_from_member.hpp +3 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/pointer_plus_bits.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/pointer_traits.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/priority_compare.hpp +22 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/rbtree.hpp +36 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/rbtree_algorithms.hpp +43 -13
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/set.hpp +95 -8
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/set_hook.hpp +4 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/sg_set.hpp +96 -12
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/sgtree.hpp +102 -5
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/sgtree_algorithms.hpp +48 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/slist.hpp +20 -11
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/slist_hook.hpp +9 -2
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/splay_set.hpp +95 -8
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/splaytree.hpp +36 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/splaytree_algorithms.hpp +27 -0
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/treap.hpp +167 -23
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/treap_algorithms.hpp +28 -0
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/treap_set.hpp +100 -46
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/trivial_value_traits.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/unordered_set.hpp +37 -27
- data/src/cxx_supportlib/vendor-modified/boost/intrusive/unordered_set_hook.hpp +30 -14
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_lexical_streams.hpp +35 -36
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_numeric.hpp +6 -28
- data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/try_lexical_convert.hpp +20 -5
- data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/posix_api.cpp +4 -2
- data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/regex.cpp +3 -1
- data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/pthread/once.cpp +5 -0
- data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/pthread/thread.cpp +11 -7
- data/src/cxx_supportlib/vendor-modified/boost/math/policies/policy.hpp +1 -3
- data/src/cxx_supportlib/vendor-modified/boost/math/special_functions/fpclassify.hpp +5 -1
- data/src/cxx_supportlib/vendor-modified/boost/math/special_functions/math_fwd.hpp +11 -0
- data/src/cxx_supportlib/vendor-modified/boost/math/tools/config.hpp +10 -2
- data/src/cxx_supportlib/vendor-modified/boost/move/adl_move_swap.hpp +40 -7
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/adaptive_merge.hpp +67 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/adaptive_sort.hpp +63 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/adaptive_sort_merge.hpp +2437 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/basic_op.hpp +121 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/insertion_sort.hpp +127 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/merge.hpp +637 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/merge_sort.hpp +139 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algo/move.hpp +155 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/algorithm.hpp +1 -116
- data/src/cxx_supportlib/vendor-modified/boost/move/core.hpp +14 -13
- data/src/cxx_supportlib/vendor-modified/boost/move/default_delete.hpp +17 -1
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/config_begin.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/destruct_n.hpp +67 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/fwd_macros.hpp +227 -32
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/iterator_traits.hpp +4 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/meta_utils.hpp +30 -9
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/meta_utils_core.hpp +12 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/move_helpers.hpp +84 -80
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/placement_new.hpp +30 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/reverse_iterator.hpp +171 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/type_traits.hpp +14 -20
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/unique_ptr_meta_utils.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/move/detail/workaround.hpp +14 -0
- data/src/cxx_supportlib/vendor-modified/boost/move/iterator.hpp +32 -33
- data/src/cxx_supportlib/vendor-modified/boost/move/make_unique.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/move/unique_ptr.hpp +49 -49
- data/src/cxx_supportlib/vendor-modified/boost/move/utility.hpp +8 -7
- data/src/cxx_supportlib/vendor-modified/boost/move/utility_core.hpp +17 -16
- data/src/cxx_supportlib/vendor-modified/boost/mpl/print.hpp +3 -0
- data/src/cxx_supportlib/vendor-modified/boost/none.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/none_t.hpp +2 -3
- data/src/cxx_supportlib/vendor-modified/boost/operators.hpp +197 -255
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/old_optional_implementation.hpp +1059 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_aligned_storage.hpp +75 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_config.hpp +116 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_factory_support.hpp +36 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_reference_spec.hpp +253 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_relops.hpp +196 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_swap.hpp +117 -0
- data/src/cxx_supportlib/vendor-modified/boost/optional/optional.hpp +372 -554
- data/src/cxx_supportlib/vendor-modified/boost/optional/optional_fwd.hpp +12 -1
- data/src/cxx_supportlib/vendor-modified/boost/pool/detail/mutex.hpp +15 -7
- data/src/cxx_supportlib/vendor-modified/boost/pool/pool_alloc.hpp +24 -0
- data/src/cxx_supportlib/vendor-modified/boost/predef/compiler/intel.h +9 -2
- data/src/cxx_supportlib/vendor-modified/boost/predef/compiler/visualc.h +15 -1
- data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd.h +16 -4
- data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd/x86.h +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd/x86_amd.h +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd/x86_amd/versions.h +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/predef/os/cygwin.h +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/predef/version.h +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/predef/version_number.h +20 -1
- data/src/cxx_supportlib/vendor-modified/boost/preprocessor/cat.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/preprocessor/config/config.hpp +6 -6
- data/src/cxx_supportlib/vendor-modified/boost/preprocessor/seq/detail/binary_transform.hpp +5 -6
- data/src/cxx_supportlib/vendor-modified/boost/preprocessor/seq/detail/to_list_msvc.hpp +55 -0
- data/src/cxx_supportlib/vendor-modified/boost/preprocessor/seq/to_list.hpp +12 -0
- data/src/cxx_supportlib/vendor-modified/boost/range/const_iterator.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/range/size_type.hpp +0 -5
- data/src/cxx_supportlib/vendor-modified/boost/regex/concepts.hpp +16 -16
- data/src/cxx_supportlib/vendor-modified/boost/regex/config.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/regex/pending/unicode_iterator.hpp +3 -0
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/basic_regex_creator.hpp +102 -87
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/basic_regex_parser.hpp +45 -21
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/cpp_regex_traits.hpp +4 -4
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/fileiter.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/instances.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/match_flags.hpp +14 -2
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/mem_block_cache.hpp +46 -0
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher.hpp +5 -2
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_common.hpp +5 -14
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_non_recursive.hpp +116 -13
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_recursive.hpp +34 -0
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_format.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_traits.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_traits_defaults.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_workaround.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/regex/v4/w32_regex_traits.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/allocate_shared_array.hpp +1004 -159
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/bad_weak_ptr.hpp +9 -0
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/atomic_count.hpp +3 -0
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/shared_count.hpp +4 -58
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base.hpp +5 -2
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_clang.hpp +9 -0
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_impl.hpp +0 -8
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_has_sync.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_noexcept.hpp +30 -0
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/spinlock.hpp +3 -0
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/enable_shared_from_this.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/intrusive_ptr.hpp +28 -3
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/intrusive_ref_counter.hpp +187 -0
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/make_shared_array.hpp +52 -144
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/make_shared_object.hpp +120 -450
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/scoped_array.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/scoped_ptr.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/shared_array.hpp +7 -6
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/shared_ptr.hpp +70 -8
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/weak_ptr.hpp +6 -5
- data/src/cxx_supportlib/vendor-modified/boost/system/error_code.hpp +9 -8
- data/src/cxx_supportlib/vendor-modified/boost/system/system_error.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/thread/barrier.hpp +5 -4
- data/src/cxx_supportlib/vendor-modified/boost/thread/completion_latch.hpp +0 -1
- data/src/cxx_supportlib/vendor-modified/boost/thread/concurrent_queues/queue_views.hpp +0 -11
- data/src/cxx_supportlib/vendor-modified/boost/thread/concurrent_queues/sync_timed_queue.hpp +6 -4
- data/src/cxx_supportlib/vendor-modified/boost/thread/detail/config.hpp +11 -2
- data/src/cxx_supportlib/vendor-modified/boost/thread/detail/thread.hpp +11 -4
- data/src/cxx_supportlib/vendor-modified/boost/thread/exceptions.hpp +8 -8
- data/src/cxx_supportlib/vendor-modified/boost/thread/executors/executor.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/thread/executors/generic_executor_ref.hpp +5 -5
- data/src/cxx_supportlib/vendor-modified/boost/thread/executors/loop_executor.hpp +22 -18
- data/src/cxx_supportlib/vendor-modified/boost/thread/future.hpp +163 -55
- data/src/cxx_supportlib/vendor-modified/boost/thread/futures/launch.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/thread/futures/wait_for_all.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/thread/lock_types.hpp +9 -9
- data/src/cxx_supportlib/vendor-modified/boost/thread/locks.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/condition_variable.hpp +6 -7
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/condition_variable_fwd.hpp +17 -2
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/shared_mutex.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/thread_data.hpp +5 -5
- data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/timespec.hpp +29 -0
- data/src/cxx_supportlib/vendor-modified/boost/thread/scoped_thread.hpp +23 -18
- data/src/cxx_supportlib/vendor-modified/boost/thread/synchronized_value.hpp +6 -6
- data/src/cxx_supportlib/vendor-modified/boost/thread/thread_functors.hpp +19 -4
- data/src/cxx_supportlib/vendor-modified/boost/thread/thread_guard.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/thread/user_scheduler.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_index.hpp +265 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_index/stl_type_index.hpp +272 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_index/type_index_facade.hpp +300 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/add_reference.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/aligned_storage.hpp +6 -6
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/common_type.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/common_arithmetic_type.hpp +9 -3
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/mp_defer.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/extent.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_nothrow_assign.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_nothrow_constructor.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_nothrow_destructor.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_assign.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_copy.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_destructor.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_move_assign.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_move_constructor.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_abstract.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_array.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_assignable.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_const.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_default_constructible.hpp +21 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_destructible.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_nothrow_move_assignable.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_nothrow_move_constructible.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_pod.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_rvalue_reference.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_virtual_base_of.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_volatile.hpp +2 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/make_void.hpp +52 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/rank.hpp +1 -0
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_all_extents.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_const.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_cv.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_extent.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_pointer.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_volatile.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/type_traits/type_with_alignment.hpp +1 -1
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/fwd.hpp +40 -6
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/implementation.hpp +4986 -0
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/map.hpp +107 -0
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/set.hpp +105 -0
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_map.hpp +1814 -1255
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_map_fwd.hpp +41 -45
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_set.hpp +1498 -1161
- data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_set_fwd.hpp +40 -44
- data/src/cxx_supportlib/vendor-modified/boost/utility.hpp +2 -2
- data/src/cxx_supportlib/vendor-modified/boost/utility/base_from_member.hpp +7 -6
- data/src/cxx_supportlib/vendor-modified/boost/utility/compare_pointees.hpp +10 -2
- data/src/cxx_supportlib/vendor-modified/boost/utility/string_ref.hpp +39 -22
- data/src/cxx_supportlib/vendor-modified/boost/utility/string_view.hpp +690 -0
- data/src/cxx_supportlib/vendor-modified/boost/utility/string_view_fwd.hpp +39 -0
- data/src/cxx_supportlib/vendor-modified/boost/version.hpp +2 -2
- data/src/helper-scripts/crash-watch.rb +3 -0
- data/src/ruby_supportlib/phusion_passenger.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +2 -12
- metadata +77 -38
- data/dev/ci/inituidgid +0 -24
- data/dev/ci/run_jenkins.sh +0 -70
- data/dev/ci/run_travis.sh +0 -314
- data/doc/Design and Architecture.html +0 -2421
- data/doc/Design and Architecture.txt +0 -511
- data/doc/Security of user switching support.html +0 -1833
- data/doc/Users guide Apache.html +0 -3101
- data/doc/Users guide Apache.idmap.txt +0 -451
- data/doc/Users guide Apache.txt +0 -534
- data/doc/Users guide Nginx.html +0 -3026
- data/doc/Users guide Nginx.idmap.txt +0 -431
- data/doc/Users guide Nginx.txt +0 -451
- data/doc/Users guide Standalone.html +0 -2092
- data/doc/Users guide Standalone.idmap.txt +0 -137
- data/doc/Users guide Standalone.txt +0 -81
- data/doc/Users guide.html +0 -1606
- data/doc/Users guide.txt +0 -8
- data/src/cxx_supportlib/vendor-modified/boost/align/align.hpp +0 -20
- data/src/cxx_supportlib/vendor-modified/boost/align/detail/address.hpp +0 -29
- data/src/cxx_supportlib/vendor-modified/boost/align/detail/align.hpp +0 -40
- data/src/cxx_supportlib/vendor-modified/boost/align/detail/align_cxx11.hpp +0 -22
- data/src/cxx_supportlib/vendor-modified/boost/align/detail/is_alignment.hpp +0 -29
- data/src/cxx_supportlib/vendor-modified/boost/container/detail/hash_table.hpp +0 -383
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_allocator.hpp +0 -318
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_count_impl.hpp +0 -67
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_traits.hpp +0 -60
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_utility.hpp +0 -214
- data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_if_array.hpp +0 -34
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/allocate.hpp +0 -1128
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/buckets.hpp +0 -928
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/equivalent.hpp +0 -686
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/extract_key.hpp +0 -188
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/table.hpp +0 -873
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/unique.hpp +0 -628
- data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/util.hpp +0 -266
@@ -914,11 +914,9 @@ struct series_factor_calc<T, Digits, mpl::true_, mpl::true_>
|
|
914
914
|
template <class T, class Digits>
|
915
915
|
struct series_factor_calc<T, Digits, mpl::true_, mpl::false_>
|
916
916
|
{
|
917
|
-
BOOST_STATIC_CONSTANT(boost::uintmax_t, v = static_cast<boost::uintmax_t>(1u) << (Digits::value - 1));
|
918
|
-
|
919
917
|
static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
|
920
918
|
{
|
921
|
-
return 1 / static_cast<T>(
|
919
|
+
return 1 / static_cast<T>(static_cast<boost::uintmax_t>(1u) << (Digits::value - 1));
|
922
920
|
}
|
923
921
|
};
|
924
922
|
template <class T, class Digits>
|
@@ -129,10 +129,14 @@ inline bool is_nan_helper(T, const boost::false_type&)
|
|
129
129
|
{
|
130
130
|
return false;
|
131
131
|
}
|
132
|
-
#if defined(BOOST_MATH_USE_FLOAT128)
|
132
|
+
#if defined(BOOST_MATH_USE_FLOAT128)
|
133
133
|
#if defined(BOOST_MATH_HAS_QUADMATH_H)
|
134
134
|
inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnanq(f); }
|
135
135
|
inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnanq(f); }
|
136
|
+
#elif defined(BOOST_GNU_STDLIB) && BOOST_GNU_STDLIB && \
|
137
|
+
_GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
|
138
|
+
inline bool is_nan_helper(__float128 f, const boost::true_type&) { return std::isnan(static_cast<double>(f)); }
|
139
|
+
inline bool is_nan_helper(__float128 f, const boost::false_type&) { return std::isnan(static_cast<double>(f)); }
|
136
140
|
#else
|
137
141
|
inline bool is_nan_helper(__float128 f, const boost::true_type&) { return ::isnan(static_cast<double>(f)); }
|
138
142
|
inline bool is_nan_helper(__float128 f, const boost::false_type&) { return ::isnan(static_cast<double>(f)); }
|
@@ -626,6 +626,17 @@ namespace boost
|
|
626
626
|
bessel_maybe_int_tag
|
627
627
|
>::type
|
628
628
|
>::type optimisation_tag;
|
629
|
+
typedef typename mpl::if_<
|
630
|
+
mpl::or_<
|
631
|
+
mpl::less_equal<precision_type, mpl::int_<0> >,
|
632
|
+
mpl::greater<precision_type, mpl::int_<113> > >,
|
633
|
+
bessel_no_int_tag,
|
634
|
+
typename mpl::if_<
|
635
|
+
is_integral<T1>,
|
636
|
+
bessel_int_tag,
|
637
|
+
bessel_maybe_int_tag
|
638
|
+
>::type
|
639
|
+
>::type optimisation_tag128;
|
629
640
|
};
|
630
641
|
} // detail
|
631
642
|
|
@@ -31,7 +31,7 @@
|
|
31
31
|
#if (defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__NetBSD__) \
|
32
32
|
|| (defined(__hppa) && !defined(__OpenBSD__)) || (defined(__NO_LONG_DOUBLE_MATH) && (DBL_MANT_DIG != LDBL_MANT_DIG))) \
|
33
33
|
&& !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
|
34
|
-
|
34
|
+
//# define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
35
35
|
#endif
|
36
36
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|
37
37
|
//
|
@@ -442,8 +442,16 @@ namespace boost{ namespace math{
|
|
442
442
|
|
443
443
|
#endif
|
444
444
|
|
445
|
-
|
445
|
+
//
|
446
|
+
// Thread local storage:
|
447
|
+
//
|
448
|
+
#if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL)
|
449
|
+
# define BOOST_MATH_THREAD_LOCAL thread_local
|
450
|
+
#else
|
451
|
+
# define BOOST_MATH_THREAD_LOCAL
|
452
|
+
#endif
|
446
453
|
|
454
|
+
#endif // BOOST_MATH_TOOLS_CONFIG_HPP
|
447
455
|
|
448
456
|
|
449
457
|
|
@@ -22,9 +22,8 @@
|
|
22
22
|
|
23
23
|
//Based on Boost.Core's swap.
|
24
24
|
//Many thanks to Steven Watanabe, Joseph Gauterin and Niels Dekker.
|
25
|
-
|
26
|
-
#include <boost/config.hpp>
|
27
25
|
#include <cstddef> //for std::size_t
|
26
|
+
#include <boost/move/detail/workaround.hpp> //forceinline
|
28
27
|
|
29
28
|
//Try to avoid including <algorithm>, as it's quite big
|
30
29
|
#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
|
@@ -156,7 +155,7 @@ struct and_op_not
|
|
156
155
|
{};
|
157
156
|
|
158
157
|
template<class T>
|
159
|
-
void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
|
158
|
+
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
|
160
159
|
{
|
161
160
|
//use std::swap if argument dependent lookup fails
|
162
161
|
//Use using directive ("using namespace xxx;") instead as some older compilers
|
@@ -166,14 +165,14 @@ void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::mov
|
|
166
165
|
}
|
167
166
|
|
168
167
|
template<class T>
|
169
|
-
void swap_proxy(T& x, T& y
|
168
|
+
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
|
170
169
|
, typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
|
171
170
|
, boost_move_member_swap::has_member_swap<T> >
|
172
171
|
>::type* = 0)
|
173
172
|
{ T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); }
|
174
173
|
|
175
174
|
template<class T>
|
176
|
-
void swap_proxy(T& x, T& y
|
175
|
+
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
|
177
176
|
, typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
|
178
177
|
, boost_move_member_swap::has_member_swap<T> >
|
179
178
|
>::type* = 0)
|
@@ -186,7 +185,7 @@ void swap_proxy(T& x, T& y
|
|
186
185
|
namespace boost_move_adl_swap{
|
187
186
|
|
188
187
|
template<class T>
|
189
|
-
void swap_proxy(T& x, T& y)
|
188
|
+
BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y)
|
190
189
|
{
|
191
190
|
using std::swap;
|
192
191
|
swap(x, y);
|
@@ -223,11 +222,45 @@ namespace boost{
|
|
223
222
|
//! - Otherwise a move-based swap is called, equivalent to:
|
224
223
|
//! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
|
225
224
|
template<class T>
|
226
|
-
void adl_move_swap(T& x, T& y)
|
225
|
+
BOOST_MOVE_FORCEINLINE void adl_move_swap(T& x, T& y)
|
227
226
|
{
|
228
227
|
::boost_move_adl_swap::swap_proxy(x, y);
|
229
228
|
}
|
230
229
|
|
230
|
+
//! Exchanges elements between range [first1, last1) and another range starting at first2
|
231
|
+
//! using boost::adl_move_swap.
|
232
|
+
//!
|
233
|
+
//! Parameters:
|
234
|
+
//! first1, last1 - the first range of elements to swap
|
235
|
+
//! first2 - beginning of the second range of elements to swap
|
236
|
+
//!
|
237
|
+
//! Type requirements:
|
238
|
+
//! - ForwardIt1, ForwardIt2 must meet the requirements of ForwardIterator.
|
239
|
+
//! - The types of dereferenced ForwardIt1 and ForwardIt2 must meet the
|
240
|
+
//! requirements of Swappable
|
241
|
+
//!
|
242
|
+
//! Return value: Iterator to the element past the last element exchanged in the range
|
243
|
+
//! beginning with first2.
|
244
|
+
template<class ForwardIt1, class ForwardIt2>
|
245
|
+
ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
|
246
|
+
{
|
247
|
+
while (first1 != last1) {
|
248
|
+
::boost::adl_move_swap(*first1, *first2);
|
249
|
+
++first1;
|
250
|
+
++first2;
|
251
|
+
}
|
252
|
+
return first2;
|
253
|
+
}
|
254
|
+
|
255
|
+
template<class BidirIt1, class BidirIt2>
|
256
|
+
BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2)
|
257
|
+
{
|
258
|
+
while (first1 != last1) {
|
259
|
+
::boost::adl_move_swap(*(--last1), *(--last2));
|
260
|
+
}
|
261
|
+
return last2;
|
262
|
+
}
|
263
|
+
|
231
264
|
} //namespace boost{
|
232
265
|
|
233
266
|
#endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
|
@@ -0,0 +1,67 @@
|
|
1
|
+
//////////////////////////////////////////////////////////////////////////////
|
2
|
+
//
|
3
|
+
// (C) Copyright Ion Gaztanaga 2015-2016.
|
4
|
+
// Distributed under the Boost Software License, Version 1.0.
|
5
|
+
// (See accompanying file LICENSE_1_0.txt or copy at
|
6
|
+
// http://www.boost.org/LICENSE_1_0.txt)
|
7
|
+
//
|
8
|
+
// See http://www.boost.org/libs/move for documentation.
|
9
|
+
//
|
10
|
+
//////////////////////////////////////////////////////////////////////////////
|
11
|
+
|
12
|
+
#ifndef BOOST_MOVE_ADAPTIVE_MERGE_HPP
|
13
|
+
#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
|
14
|
+
|
15
|
+
#include <boost/move/detail/config_begin.hpp>
|
16
|
+
#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
|
17
|
+
|
18
|
+
namespace boost {
|
19
|
+
namespace movelib {
|
20
|
+
|
21
|
+
//! <b>Effects</b>: Merges two consecutive sorted ranges [first, middle) and [middle, last)
|
22
|
+
//! into one sorted range [first, last) according to the given comparison function comp.
|
23
|
+
//! The algorithm is stable (if there are equivalent elements in the original two ranges,
|
24
|
+
//! the elements from the first range (preserving their original order) precede the elements
|
25
|
+
//! from the second range (preserving their original order).
|
26
|
+
//!
|
27
|
+
//! <b>Requires</b>:
|
28
|
+
//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
|
29
|
+
//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
|
30
|
+
//!
|
31
|
+
//! <b>Parameters</b>:
|
32
|
+
//! - first: the beginning of the first sorted range.
|
33
|
+
//! - middle: the end of the first sorted range and the beginning of the second
|
34
|
+
//! - last: the end of the second sorted range
|
35
|
+
//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
|
36
|
+
//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
|
37
|
+
//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
|
38
|
+
//! is min(std::distance(first, middle), std::distance(middle, last)).
|
39
|
+
//!
|
40
|
+
//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
|
41
|
+
//! of dereferenced RandIt throws.
|
42
|
+
//!
|
43
|
+
//! <b>Complexity</b>: Always K x O(N) comparisons and move assignments/constructors/swaps.
|
44
|
+
//! Constant factor for comparisons and data movement is minimized when uninitialized_len
|
45
|
+
//! is min(std::distance(first, middle), std::distance(middle, last)).
|
46
|
+
//! Pretty good enough performance is achieved when uninitialized_len is
|
47
|
+
//! ceil(sqrt(std::distance(first, last)))*2.
|
48
|
+
//!
|
49
|
+
//! <b>Caution</b>: Experimental implementation, not production-ready.
|
50
|
+
template<class RandIt, class Compare>
|
51
|
+
void adaptive_merge( RandIt first, RandIt middle, RandIt last, Compare comp
|
52
|
+
, typename iterator_traits<RandIt>::value_type* uninitialized = 0
|
53
|
+
, std::size_t uninitialized_len = 0)
|
54
|
+
{
|
55
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
56
|
+
typedef typename iterator_traits<RandIt>::value_type value_type;
|
57
|
+
|
58
|
+
::boost::movelib::detail_adaptive::adaptive_xbuf<value_type> xbuf(uninitialized, uninitialized_len);
|
59
|
+
::boost::movelib::detail_adaptive::adaptive_merge_impl(first, size_type(middle - first), size_type(last - middle), comp, xbuf);
|
60
|
+
}
|
61
|
+
|
62
|
+
} //namespace movelib {
|
63
|
+
} //namespace boost {
|
64
|
+
|
65
|
+
#include <boost/move/detail/config_end.hpp>
|
66
|
+
|
67
|
+
#endif //#define BOOST_MOVE_ADAPTIVE_MERGE_HPP
|
@@ -0,0 +1,63 @@
|
|
1
|
+
//////////////////////////////////////////////////////////////////////////////
|
2
|
+
//
|
3
|
+
// (C) Copyright Ion Gaztanaga 2015-2016.
|
4
|
+
// Distributed under the Boost Software License, Version 1.0.
|
5
|
+
// (See accompanying file LICENSE_1_0.txt or copy at
|
6
|
+
// http://www.boost.org/LICENSE_1_0.txt)
|
7
|
+
//
|
8
|
+
// See http://www.boost.org/libs/move for documentation.
|
9
|
+
//
|
10
|
+
//////////////////////////////////////////////////////////////////////////////
|
11
|
+
|
12
|
+
#ifndef BOOST_MOVE_ADAPTIVE_SORT_HPP
|
13
|
+
#define BOOST_MOVE_ADAPTIVE_SORT_HPP
|
14
|
+
|
15
|
+
#include <boost/move/detail/config_begin.hpp>
|
16
|
+
#include <boost/move/algo/detail/adaptive_sort_merge.hpp>
|
17
|
+
|
18
|
+
namespace boost {
|
19
|
+
namespace movelib {
|
20
|
+
|
21
|
+
//! <b>Effects</b>: Sorts the elements in the range [first, last) in ascending order according
|
22
|
+
//! to comparison functor "comp". The sort is stable (order of equal elements
|
23
|
+
//! is guaranteed to be preserved). Performance is improved if additional raw storage is
|
24
|
+
//! provided.
|
25
|
+
//!
|
26
|
+
//! <b>Requires</b>:
|
27
|
+
//! - RandIt must meet the requirements of ValueSwappable and RandomAccessIterator.
|
28
|
+
//! - The type of dereferenced RandIt must meet the requirements of MoveAssignable and MoveConstructible.
|
29
|
+
//!
|
30
|
+
//! <b>Parameters</b>:
|
31
|
+
//! - first, last: the range of elements to sort
|
32
|
+
//! - comp: comparison function object which returns true if the first argument is is ordered before the second.
|
33
|
+
//! - uninitialized, uninitialized_len: raw storage starting on "uninitialized", able to hold "uninitialized_len"
|
34
|
+
//! elements of type iterator_traits<RandIt>::value_type. Maximum performance is achieved when uninitialized_len
|
35
|
+
//! is ceil(std::distance(first, last)/2).
|
36
|
+
//!
|
37
|
+
//! <b>Throws</b>: If comp throws or the move constructor, move assignment or swap of the type
|
38
|
+
//! of dereferenced RandIt throws.
|
39
|
+
//!
|
40
|
+
//! <b>Complexity</b>: Always K x O(Nxlog(N)) comparisons and move assignments/constructors/swaps.
|
41
|
+
//! Comparisons are close to minimum even with no additional memory. Constant factor for data movement is minimized
|
42
|
+
//! when uninitialized_len is ceil(std::distance(first, last)/2). Pretty good enough performance is achieved when
|
43
|
+
//! ceil(sqrt(std::distance(first, last)))*2.
|
44
|
+
//!
|
45
|
+
//! <b>Caution</b>: Experimental implementation, not production-ready.
|
46
|
+
template<class RandIt, class Compare>
|
47
|
+
void adaptive_sort( RandIt first, RandIt last, Compare comp
|
48
|
+
, typename iterator_traits<RandIt>::value_type* uninitialized = 0
|
49
|
+
, std::size_t uninitialized_len = 0)
|
50
|
+
{
|
51
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
52
|
+
typedef typename iterator_traits<RandIt>::value_type value_type;
|
53
|
+
|
54
|
+
::boost::movelib::detail_adaptive::adaptive_xbuf<value_type> xbuf(uninitialized, uninitialized_len);
|
55
|
+
::boost::movelib::detail_adaptive::adaptive_sort_impl(first, size_type(last - first), comp, xbuf);
|
56
|
+
}
|
57
|
+
|
58
|
+
} //namespace movelib {
|
59
|
+
} //namespace boost {
|
60
|
+
|
61
|
+
#include <boost/move/detail/config_end.hpp>
|
62
|
+
|
63
|
+
#endif //#define BOOST_MOVE_ADAPTIVE_SORT_HPP
|
@@ -0,0 +1,2437 @@
|
|
1
|
+
//////////////////////////////////////////////////////////////////////////////
|
2
|
+
//
|
3
|
+
// (C) Copyright Ion Gaztanaga 2015-2016.
|
4
|
+
// Distributed under the Boost Software License, Version 1.0.
|
5
|
+
// (See accompanying file LICENSE_1_0.txt or copy at
|
6
|
+
// http://www.boost.org/LICENSE_1_0.txt)
|
7
|
+
//
|
8
|
+
// See http://www.boost.org/libs/move for documentation.
|
9
|
+
//
|
10
|
+
//////////////////////////////////////////////////////////////////////////////
|
11
|
+
//
|
12
|
+
// Stable sorting that works in O(N*log(N)) worst time
|
13
|
+
// and uses O(1) extra memory
|
14
|
+
//
|
15
|
+
//////////////////////////////////////////////////////////////////////////////
|
16
|
+
//
|
17
|
+
// The main idea of the adaptive_sort algorithm was developed by Andrey Astrelin
|
18
|
+
// and explained in the article from the russian collaborative blog
|
19
|
+
// Habrahabr (http://habrahabr.ru/post/205290/). The algorithm is based on
|
20
|
+
// ideas from B-C. Huang and M. A. Langston explained in their article
|
21
|
+
// "Fast Stable Merging and Sorting in Constant Extra Space (1989-1992)"
|
22
|
+
// (http://comjnl.oxfordjournals.org/content/35/6/643.full.pdf).
|
23
|
+
//
|
24
|
+
// This implementation by Ion Gaztanaga uses previous ideas with additional changes:
|
25
|
+
//
|
26
|
+
// - Use of GCD-based rotation.
|
27
|
+
// - Non power of two buffer-sizes.
|
28
|
+
// - Tries to find sqrt(len)*2 unique keys, so that the merge sort
|
29
|
+
// phase can form up to sqrt(len)*4 segments if enough keys are found.
|
30
|
+
// - The merge-sort phase can take advantage of external memory to
|
31
|
+
// save some additional combination steps.
|
32
|
+
// - Combination phase: Blocks are selection sorted and merged in parallel.
|
33
|
+
// - The combination phase is performed alternating merge to left and merge
|
34
|
+
// to right phases minimizing swaps due to internal buffer repositioning.
|
35
|
+
// - When merging blocks special optimizations are made to avoid moving some
|
36
|
+
// elements twice.
|
37
|
+
//
|
38
|
+
// The adaptive_merge algorithm was developed by Ion Gaztanaga reusing some parts
|
39
|
+
// from the sorting algorithm and implementing an additional block merge algorithm
|
40
|
+
// without moving elements to left or right.
|
41
|
+
//////////////////////////////////////////////////////////////////////////////
|
42
|
+
#ifndef BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
|
43
|
+
#define BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
|
44
|
+
|
45
|
+
#include <boost/move/detail/config_begin.hpp>
|
46
|
+
#include <boost/move/detail/reverse_iterator.hpp>
|
47
|
+
#include <boost/move/algo/move.hpp>
|
48
|
+
#include <boost/move/algo/detail/merge.hpp>
|
49
|
+
#include <boost/move/adl_move_swap.hpp>
|
50
|
+
#include <boost/move/algo/detail/insertion_sort.hpp>
|
51
|
+
#include <boost/move/algo/detail/merge_sort.hpp>
|
52
|
+
#include <boost/move/algo/detail/merge.hpp>
|
53
|
+
#include <boost/assert.hpp>
|
54
|
+
#include <boost/cstdint.hpp>
|
55
|
+
|
56
|
+
#ifdef BOOST_MOVE_ADAPTIVE_SORT_STATS
|
57
|
+
#define BOOST_MOVE_ADAPTIVE_SORT_PRINT(STR, L) \
|
58
|
+
print_stats(STR, L)\
|
59
|
+
//
|
60
|
+
#else
|
61
|
+
#define BOOST_MOVE_ADAPTIVE_SORT_PRINT(STR, L)
|
62
|
+
#endif
|
63
|
+
|
64
|
+
#ifdef BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
|
65
|
+
#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANT BOOST_ASSERT
|
66
|
+
#else
|
67
|
+
#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(L)
|
68
|
+
#endif
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
namespace boost {
|
73
|
+
namespace movelib {
|
74
|
+
|
75
|
+
namespace detail_adaptive {
|
76
|
+
|
77
|
+
static const std::size_t AdaptiveSortInsertionSortThreshold = 16;
|
78
|
+
//static const std::size_t AdaptiveSortInsertionSortThreshold = 4;
|
79
|
+
BOOST_STATIC_ASSERT((AdaptiveSortInsertionSortThreshold&(AdaptiveSortInsertionSortThreshold-1)) == 0);
|
80
|
+
|
81
|
+
#if defined BOOST_HAS_INTPTR_T
|
82
|
+
typedef ::boost::uintptr_t uintptr_t;
|
83
|
+
#else
|
84
|
+
typedef std::size_t uintptr_t;
|
85
|
+
#endif
|
86
|
+
|
87
|
+
template<class T>
|
88
|
+
const T &min_value(const T &a, const T &b)
|
89
|
+
{
|
90
|
+
return a < b ? a : b;
|
91
|
+
}
|
92
|
+
|
93
|
+
template<class T>
|
94
|
+
const T &max_value(const T &a, const T &b)
|
95
|
+
{
|
96
|
+
return a > b ? a : b;
|
97
|
+
}
|
98
|
+
|
99
|
+
template<class ForwardIt, class Pred>
|
100
|
+
bool is_sorted(ForwardIt const first, ForwardIt last, Pred pred)
|
101
|
+
{
|
102
|
+
if (first != last) {
|
103
|
+
ForwardIt next = first, cur(first);
|
104
|
+
while (++next != last) {
|
105
|
+
if (pred(*next, *cur))
|
106
|
+
return false;
|
107
|
+
cur = next;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
return true;
|
111
|
+
}
|
112
|
+
|
113
|
+
#if defined(BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS)
|
114
|
+
|
115
|
+
bool is_sorted(::order_perf_type *first, ::order_perf_type *last, ::order_type_less)
|
116
|
+
{
|
117
|
+
if (first != last) {
|
118
|
+
const order_perf_type *next = first, *cur(first);
|
119
|
+
while (++next != last) {
|
120
|
+
if (!(cur->key < next->key || (cur->key == next->key && cur->val < next->val)))
|
121
|
+
return false;
|
122
|
+
cur = next;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
return true;
|
126
|
+
}
|
127
|
+
|
128
|
+
#endif //BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
|
129
|
+
|
130
|
+
template<class ForwardIt, class Pred>
|
131
|
+
bool is_sorted_and_unique(ForwardIt first, ForwardIt last, Pred pred)
|
132
|
+
{
|
133
|
+
if (first != last) {
|
134
|
+
ForwardIt next = first;
|
135
|
+
while (++next != last) {
|
136
|
+
if (!pred(*first, *next))
|
137
|
+
return false;
|
138
|
+
first = next;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
return true;
|
142
|
+
}
|
143
|
+
|
144
|
+
template<class ForwardIt, class Pred, class V>
|
145
|
+
typename iterator_traits<ForwardIt>::size_type
|
146
|
+
count_if_with(ForwardIt first, ForwardIt last, Pred pred, const V &v)
|
147
|
+
{
|
148
|
+
typedef typename iterator_traits<ForwardIt>::size_type size_type;
|
149
|
+
size_type count = 0;
|
150
|
+
while(first != last) {
|
151
|
+
count += static_cast<size_type>(0 != pred(*first, v));
|
152
|
+
++first;
|
153
|
+
}
|
154
|
+
return count;
|
155
|
+
}
|
156
|
+
|
157
|
+
template<class T>
|
158
|
+
class adaptive_xbuf
|
159
|
+
{
|
160
|
+
adaptive_xbuf(const adaptive_xbuf &);
|
161
|
+
adaptive_xbuf & operator=(const adaptive_xbuf &);
|
162
|
+
|
163
|
+
public:
|
164
|
+
typedef T* iterator;
|
165
|
+
|
166
|
+
adaptive_xbuf()
|
167
|
+
: m_ptr(0), m_size(0), m_capacity(0)
|
168
|
+
{}
|
169
|
+
|
170
|
+
adaptive_xbuf(T *raw_memory, std::size_t capacity)
|
171
|
+
: m_ptr(raw_memory), m_size(0), m_capacity(capacity)
|
172
|
+
{}
|
173
|
+
|
174
|
+
template<class RandIt>
|
175
|
+
void move_assign(RandIt first, std::size_t n)
|
176
|
+
{
|
177
|
+
if(n <= m_size){
|
178
|
+
boost::move(first, first+n, m_ptr);
|
179
|
+
std::size_t size = m_size;
|
180
|
+
while(size-- != n){
|
181
|
+
m_ptr[size].~T();
|
182
|
+
}
|
183
|
+
m_size = n;
|
184
|
+
}
|
185
|
+
else{
|
186
|
+
T *result = boost::move(first, first+m_size, m_ptr);
|
187
|
+
boost::uninitialized_move(first+m_size, first+n, result);
|
188
|
+
m_size = n;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
template<class RandIt>
|
193
|
+
void push_back(RandIt first, std::size_t n)
|
194
|
+
{
|
195
|
+
BOOST_ASSERT(m_capacity - m_size >= n);
|
196
|
+
boost::uninitialized_move(first, first+n, m_ptr+m_size);
|
197
|
+
m_size += n;
|
198
|
+
}
|
199
|
+
|
200
|
+
template<class RandIt>
|
201
|
+
iterator add(RandIt it)
|
202
|
+
{
|
203
|
+
BOOST_ASSERT(m_size < m_capacity);
|
204
|
+
T * p_ret = m_ptr + m_size;
|
205
|
+
::new(p_ret) T(::boost::move(*it));
|
206
|
+
++m_size;
|
207
|
+
return p_ret;
|
208
|
+
}
|
209
|
+
|
210
|
+
template<class RandIt>
|
211
|
+
void insert(iterator pos, RandIt it)
|
212
|
+
{
|
213
|
+
if(pos == (m_ptr + m_size)){
|
214
|
+
this->add(it);
|
215
|
+
}
|
216
|
+
else{
|
217
|
+
this->add(m_ptr+m_size-1);
|
218
|
+
//m_size updated
|
219
|
+
boost::move_backward(pos, m_ptr+m_size-2, m_ptr+m_size-1);
|
220
|
+
*pos = boost::move(*it);
|
221
|
+
}
|
222
|
+
}
|
223
|
+
|
224
|
+
void set_size(std::size_t size)
|
225
|
+
{
|
226
|
+
m_size = size;
|
227
|
+
}
|
228
|
+
|
229
|
+
void shrink_to_fit(std::size_t const size)
|
230
|
+
{
|
231
|
+
if(m_size > size){
|
232
|
+
for(std::size_t szt_i = size; szt_i != m_size; ++szt_i){
|
233
|
+
m_ptr[szt_i].~T();
|
234
|
+
}
|
235
|
+
m_size = size;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
void initialize_until(std::size_t const size, T &t)
|
240
|
+
{
|
241
|
+
BOOST_ASSERT(m_size < m_capacity);
|
242
|
+
if(m_size < size){
|
243
|
+
::new((void*)&m_ptr[m_size]) T(::boost::move(t));
|
244
|
+
++m_size;
|
245
|
+
for(; m_size != size; ++m_size){
|
246
|
+
::new((void*)&m_ptr[m_size]) T(::boost::move(m_ptr[m_size-1]));
|
247
|
+
}
|
248
|
+
t = ::boost::move(m_ptr[m_size-1]);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
template<class U>
|
253
|
+
bool supports_aligned_trailing(std::size_t size, std::size_t trail_count) const
|
254
|
+
{
|
255
|
+
if(this->data()){
|
256
|
+
uintptr_t u_addr_sz = uintptr_t(this->data()+size);
|
257
|
+
uintptr_t u_addr_cp = uintptr_t(this->data()+this->capacity());
|
258
|
+
u_addr_sz = ((u_addr_sz + sizeof(U)-1)/sizeof(U))*sizeof(U);
|
259
|
+
|
260
|
+
return (u_addr_cp >= u_addr_sz) && ((u_addr_cp - u_addr_sz)/sizeof(U) >= trail_count);
|
261
|
+
}
|
262
|
+
return false;
|
263
|
+
}
|
264
|
+
|
265
|
+
template<class U>
|
266
|
+
U *aligned_trailing() const
|
267
|
+
{
|
268
|
+
return this->aligned_trailing<U>(this->size());
|
269
|
+
}
|
270
|
+
|
271
|
+
template<class U>
|
272
|
+
U *aligned_trailing(std::size_t pos) const
|
273
|
+
{
|
274
|
+
uintptr_t u_addr = uintptr_t(this->data()+pos);
|
275
|
+
u_addr = ((u_addr + sizeof(U)-1)/sizeof(U))*sizeof(U);
|
276
|
+
return (U*)u_addr;
|
277
|
+
}
|
278
|
+
|
279
|
+
~adaptive_xbuf()
|
280
|
+
{
|
281
|
+
this->clear();
|
282
|
+
}
|
283
|
+
|
284
|
+
std::size_t capacity() const
|
285
|
+
{ return m_capacity; }
|
286
|
+
|
287
|
+
iterator data() const
|
288
|
+
{ return m_ptr; }
|
289
|
+
|
290
|
+
iterator end() const
|
291
|
+
{ return m_ptr+m_size; }
|
292
|
+
|
293
|
+
std::size_t size() const
|
294
|
+
{ return m_size; }
|
295
|
+
|
296
|
+
bool empty() const
|
297
|
+
{ return !m_size; }
|
298
|
+
|
299
|
+
void clear()
|
300
|
+
{
|
301
|
+
this->shrink_to_fit(0u);
|
302
|
+
}
|
303
|
+
|
304
|
+
private:
|
305
|
+
T *m_ptr;
|
306
|
+
std::size_t m_size;
|
307
|
+
std::size_t m_capacity;
|
308
|
+
};
|
309
|
+
|
310
|
+
template<class Iterator, class Op>
|
311
|
+
class range_xbuf
|
312
|
+
{
|
313
|
+
range_xbuf(const range_xbuf &);
|
314
|
+
range_xbuf & operator=(const range_xbuf &);
|
315
|
+
|
316
|
+
public:
|
317
|
+
typedef typename iterator_traits<Iterator>::size_type size_type;
|
318
|
+
typedef Iterator iterator;
|
319
|
+
|
320
|
+
range_xbuf(Iterator first, Iterator last)
|
321
|
+
: m_first(first), m_last(first), m_cap(last)
|
322
|
+
{}
|
323
|
+
|
324
|
+
template<class RandIt>
|
325
|
+
void move_assign(RandIt first, std::size_t n)
|
326
|
+
{
|
327
|
+
BOOST_ASSERT(size_type(n) <= size_type(m_cap-m_first));
|
328
|
+
m_last = Op()(forward_t(), first, first+n, m_first);
|
329
|
+
}
|
330
|
+
|
331
|
+
~range_xbuf()
|
332
|
+
{}
|
333
|
+
|
334
|
+
std::size_t capacity() const
|
335
|
+
{ return m_cap-m_first; }
|
336
|
+
|
337
|
+
Iterator data() const
|
338
|
+
{ return m_first; }
|
339
|
+
|
340
|
+
Iterator end() const
|
341
|
+
{ return m_last; }
|
342
|
+
|
343
|
+
std::size_t size() const
|
344
|
+
{ return m_last-m_first; }
|
345
|
+
|
346
|
+
bool empty() const
|
347
|
+
{ return m_first == m_last; }
|
348
|
+
|
349
|
+
void clear()
|
350
|
+
{
|
351
|
+
m_last = m_first;
|
352
|
+
}
|
353
|
+
|
354
|
+
template<class RandIt>
|
355
|
+
iterator add(RandIt it)
|
356
|
+
{
|
357
|
+
Iterator pos(m_last);
|
358
|
+
*pos = boost::move(*it);
|
359
|
+
++m_last;
|
360
|
+
return pos;
|
361
|
+
}
|
362
|
+
|
363
|
+
void set_size(std::size_t size)
|
364
|
+
{
|
365
|
+
m_last = m_first;
|
366
|
+
m_last += size;
|
367
|
+
}
|
368
|
+
|
369
|
+
private:
|
370
|
+
Iterator const m_first;
|
371
|
+
Iterator m_last;
|
372
|
+
Iterator const m_cap;
|
373
|
+
};
|
374
|
+
|
375
|
+
|
376
|
+
template<class RandIt, class Compare>
|
377
|
+
RandIt skip_until_merge
|
378
|
+
( RandIt first1, RandIt const last1
|
379
|
+
, const typename iterator_traits<RandIt>::value_type &next_key, Compare comp)
|
380
|
+
{
|
381
|
+
while(first1 != last1 && !comp(next_key, *first1)){
|
382
|
+
++first1;
|
383
|
+
}
|
384
|
+
return first1;
|
385
|
+
}
|
386
|
+
|
387
|
+
|
388
|
+
template<class RandIt1, class RandIt2, class RandItB, class Compare, class Op>
|
389
|
+
RandItB op_buffered_partial_merge_to_range1_and_buffer
|
390
|
+
( RandIt1 first1, RandIt1 const last1
|
391
|
+
, RandIt2 &rfirst2, RandIt2 const last2
|
392
|
+
, RandItB &rfirstb, Compare comp, Op op )
|
393
|
+
{
|
394
|
+
RandItB firstb = rfirstb;
|
395
|
+
RandItB lastb = firstb;
|
396
|
+
RandIt2 first2 = rfirst2;
|
397
|
+
|
398
|
+
//Move to buffer while merging
|
399
|
+
//Three way moves need less moves when op is swap_op so use it
|
400
|
+
//when merging elements from range2 to the destination occupied by range1
|
401
|
+
if(first1 != last1 && first2 != last2){
|
402
|
+
op(three_way_t(), first2++, first1++, lastb++);
|
403
|
+
|
404
|
+
while(true){
|
405
|
+
if(first1 == last1){
|
406
|
+
break;
|
407
|
+
}
|
408
|
+
if(first2 == last2){
|
409
|
+
lastb = op(forward_t(), first1, last1, firstb);
|
410
|
+
break;
|
411
|
+
}
|
412
|
+
op(three_way_t(), comp(*first2, *firstb) ? first2++ : firstb++, first1++, lastb++);
|
413
|
+
}
|
414
|
+
rfirst2 = first2;
|
415
|
+
rfirstb = firstb;
|
416
|
+
}
|
417
|
+
|
418
|
+
return lastb;
|
419
|
+
}
|
420
|
+
|
421
|
+
template<class RandItKeys, class RandIt>
|
422
|
+
void swap_and_update_key
|
423
|
+
( bool is_next_far_away
|
424
|
+
, RandItKeys const key_next
|
425
|
+
, RandItKeys const key_range2
|
426
|
+
, RandItKeys &key_mid
|
427
|
+
, RandIt const begin
|
428
|
+
, RandIt const end
|
429
|
+
, RandIt const with)
|
430
|
+
{
|
431
|
+
if(is_next_far_away){
|
432
|
+
::boost::adl_move_swap_ranges(begin, end, with);
|
433
|
+
::boost::adl_move_swap(*key_next, *key_range2);
|
434
|
+
if(key_next == key_mid){
|
435
|
+
key_mid = key_range2;
|
436
|
+
}
|
437
|
+
else if(key_mid == key_range2){
|
438
|
+
key_mid = key_next;
|
439
|
+
}
|
440
|
+
}
|
441
|
+
}
|
442
|
+
|
443
|
+
///////////////////////////////////////////////////////////////////////////////
|
444
|
+
//
|
445
|
+
// MERGE BUFFERLESS
|
446
|
+
//
|
447
|
+
///////////////////////////////////////////////////////////////////////////////
|
448
|
+
|
449
|
+
// [first1, last1) merge [last1,last2) -> [first1,last2)
|
450
|
+
template<class RandIt, class Compare>
|
451
|
+
RandIt partial_merge_bufferless_impl
|
452
|
+
(RandIt first1, RandIt last1, RandIt const last2, bool *const pis_range1_A, Compare comp)
|
453
|
+
{
|
454
|
+
if(last1 == last2){
|
455
|
+
return first1;
|
456
|
+
}
|
457
|
+
bool const is_range1_A = *pis_range1_A;
|
458
|
+
if(first1 != last1 && comp(*last1, last1[-1])){
|
459
|
+
do{
|
460
|
+
RandIt const old_last1 = last1;
|
461
|
+
last1 = lower_bound(last1, last2, *first1, comp);
|
462
|
+
first1 = rotate_gcd(first1, old_last1, last1);//old_last1 == last1 supported
|
463
|
+
if(last1 == last2){
|
464
|
+
return first1;
|
465
|
+
}
|
466
|
+
do{
|
467
|
+
++first1;
|
468
|
+
} while(last1 != first1 && !comp(*last1, *first1) );
|
469
|
+
} while(first1 != last1);
|
470
|
+
}
|
471
|
+
*pis_range1_A = !is_range1_A;
|
472
|
+
return last1;
|
473
|
+
}
|
474
|
+
|
475
|
+
// [first1, last1) merge [last1,last2) -> [first1,last2)
|
476
|
+
template<class RandIt, class Compare>
|
477
|
+
RandIt partial_merge_bufferless
|
478
|
+
(RandIt first1, RandIt last1, RandIt const last2, bool *const pis_range1_A, Compare comp)
|
479
|
+
{
|
480
|
+
return *pis_range1_A ? partial_merge_bufferless_impl(first1, last1, last2, pis_range1_A, comp)
|
481
|
+
: partial_merge_bufferless_impl(first1, last1, last2, pis_range1_A, antistable<Compare>(comp));
|
482
|
+
}
|
483
|
+
|
484
|
+
template<class SizeType>
|
485
|
+
static SizeType needed_keys_count(SizeType n_block_a, SizeType n_block_b)
|
486
|
+
{
|
487
|
+
return n_block_a + n_block_b;
|
488
|
+
}
|
489
|
+
|
490
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
|
491
|
+
typename iterator_traits<RandIt>::size_type
|
492
|
+
find_next_block
|
493
|
+
( RandItKeys key_first
|
494
|
+
, KeyCompare key_comp
|
495
|
+
, RandIt const first
|
496
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
497
|
+
, typename iterator_traits<RandIt>::size_type const ix_first_block
|
498
|
+
, typename iterator_traits<RandIt>::size_type const ix_last_block
|
499
|
+
, Compare comp)
|
500
|
+
{
|
501
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
502
|
+
typedef typename iterator_traits<RandIt>::value_type value_type;
|
503
|
+
typedef typename iterator_traits<RandItKeys>::value_type key_type;
|
504
|
+
BOOST_ASSERT(ix_first_block <= ix_last_block);
|
505
|
+
size_type ix_min_block = 0u;
|
506
|
+
for (size_type szt_i = ix_first_block; szt_i < ix_last_block; ++szt_i) {
|
507
|
+
const value_type &min_val = first[ix_min_block*l_block];
|
508
|
+
const value_type &cur_val = first[szt_i*l_block];
|
509
|
+
const key_type &min_key = key_first[ix_min_block];
|
510
|
+
const key_type &cur_key = key_first[szt_i];
|
511
|
+
|
512
|
+
bool const less_than_minimum = comp(cur_val, min_val) ||
|
513
|
+
(!comp(min_val, cur_val) && key_comp(cur_key, min_key));
|
514
|
+
|
515
|
+
if (less_than_minimum) {
|
516
|
+
ix_min_block = szt_i;
|
517
|
+
}
|
518
|
+
}
|
519
|
+
return ix_min_block;
|
520
|
+
}
|
521
|
+
|
522
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
|
523
|
+
void merge_blocks_bufferless
|
524
|
+
( RandItKeys key_first
|
525
|
+
, KeyCompare key_comp
|
526
|
+
, RandIt const first
|
527
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
528
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg1
|
529
|
+
, typename iterator_traits<RandIt>::size_type const n_block_a
|
530
|
+
, typename iterator_traits<RandIt>::size_type const n_block_b
|
531
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg2
|
532
|
+
, Compare comp)
|
533
|
+
{
|
534
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
535
|
+
size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
|
536
|
+
//BOOST_ASSERT(n_block_a || n_block_b);
|
537
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted_and_unique(key_first, key_first + key_count, key_comp));
|
538
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
|
539
|
+
|
540
|
+
size_type n_bef_irreg2 = 0;
|
541
|
+
bool l_irreg_pos_count = true;
|
542
|
+
RandItKeys key_mid(key_first + n_block_a);
|
543
|
+
RandIt const first_irr2 = first + l_irreg1 + (n_block_a+n_block_b)*l_block;
|
544
|
+
RandIt const last_irr2 = first_irr2 + l_irreg2;
|
545
|
+
|
546
|
+
{ //Selection sort blocks
|
547
|
+
size_type n_block_left = n_block_b + n_block_a;
|
548
|
+
RandItKeys key_range2(key_first);
|
549
|
+
|
550
|
+
size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
|
551
|
+
size_type max_check = min_value(min_check+1, n_block_left);
|
552
|
+
for (RandIt f = first+l_irreg1; n_block_left; --n_block_left, ++key_range2, f += l_block, min_check -= min_check != 0, max_check -= max_check != 0) {
|
553
|
+
size_type const next_key_idx = find_next_block(key_range2, key_comp, f, l_block, min_check, max_check, comp);
|
554
|
+
RandItKeys const key_next(key_range2 + next_key_idx);
|
555
|
+
max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
|
556
|
+
|
557
|
+
RandIt const first_min = f + next_key_idx*l_block;
|
558
|
+
|
559
|
+
//Check if irregular b block should go here.
|
560
|
+
//If so, break to the special code handling the irregular block
|
561
|
+
if (l_irreg_pos_count && l_irreg2 && comp(*first_irr2, *first_min)){
|
562
|
+
l_irreg_pos_count = false;
|
563
|
+
}
|
564
|
+
n_bef_irreg2 += l_irreg_pos_count;
|
565
|
+
|
566
|
+
swap_and_update_key(next_key_idx != 0, key_next, key_range2, key_mid, f, f + l_block, first_min);
|
567
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(f, f+l_block, comp));
|
568
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, first_min + l_block, comp));
|
569
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((f == (first+l_irreg1)) || !comp(*f, *(f-l_block)));
|
570
|
+
}
|
571
|
+
}
|
572
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first+l_irreg1+n_bef_irreg2*l_block, first_irr2, comp));
|
573
|
+
|
574
|
+
RandIt first1 = first;
|
575
|
+
RandIt last1 = first+l_irreg1;
|
576
|
+
RandItKeys const key_end (key_first+n_bef_irreg2);
|
577
|
+
bool is_range1_A = true;
|
578
|
+
|
579
|
+
for( ; key_first != key_end; ++key_first){
|
580
|
+
bool is_range2_A = key_mid == (key_first+key_count) || key_comp(*key_first, *key_mid);
|
581
|
+
first1 = is_range1_A == is_range2_A
|
582
|
+
? last1 : partial_merge_bufferless(first1, last1, last1 + l_block, &is_range1_A, comp);
|
583
|
+
last1 += l_block;
|
584
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, first1, comp));
|
585
|
+
}
|
586
|
+
|
587
|
+
merge_bufferless(is_range1_A ? first1 : last1, first_irr2, last_irr2, comp);
|
588
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, last_irr2, comp));
|
589
|
+
}
|
590
|
+
|
591
|
+
///////////////////////////////////////////////////////////////////////////////
|
592
|
+
//
|
593
|
+
// BUFFERED MERGE
|
594
|
+
//
|
595
|
+
///////////////////////////////////////////////////////////////////////////////
|
596
|
+
template<class RandIt, class Compare, class Op, class Buf>
|
597
|
+
void op_buffered_merge
|
598
|
+
( RandIt first, RandIt const middle, RandIt last
|
599
|
+
, Compare comp, Op op
|
600
|
+
, Buf &xbuf)
|
601
|
+
{
|
602
|
+
if(first != middle && middle != last && comp(*middle, middle[-1])){
|
603
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
604
|
+
size_type const len1 = size_type(middle-first);
|
605
|
+
size_type const len2 = size_type(last-middle);
|
606
|
+
if(len1 <= len2){
|
607
|
+
first = upper_bound(first, middle, *middle, comp);
|
608
|
+
xbuf.move_assign(first, size_type(middle-first));
|
609
|
+
op_merge_with_right_placed
|
610
|
+
(xbuf.data(), xbuf.end(), first, middle, last, comp, op);
|
611
|
+
}
|
612
|
+
else{
|
613
|
+
last = lower_bound(middle, last, middle[-1], comp);
|
614
|
+
xbuf.move_assign(middle, size_type(last-middle));
|
615
|
+
op_merge_with_left_placed
|
616
|
+
(first, middle, last, xbuf.data(), xbuf.end(), comp, op);
|
617
|
+
}
|
618
|
+
}
|
619
|
+
}
|
620
|
+
|
621
|
+
template<class RandIt, class Compare>
|
622
|
+
void buffered_merge
|
623
|
+
( RandIt first, RandIt const middle, RandIt last
|
624
|
+
, Compare comp
|
625
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> &xbuf)
|
626
|
+
{
|
627
|
+
op_buffered_merge(first, middle, last, comp, move_op(), xbuf);
|
628
|
+
}
|
629
|
+
|
630
|
+
// Complexity: 2*distance(first, last)+max_collected^2/2
|
631
|
+
//
|
632
|
+
// Tries to collect at most n_keys unique elements from [first, last),
|
633
|
+
// in the begining of the range, and ordered according to comp
|
634
|
+
//
|
635
|
+
// Returns the number of collected keys
|
636
|
+
template<class RandIt, class Compare>
|
637
|
+
typename iterator_traits<RandIt>::size_type
|
638
|
+
collect_unique
|
639
|
+
( RandIt const first, RandIt const last
|
640
|
+
, typename iterator_traits<RandIt>::size_type const max_collected, Compare comp
|
641
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf)
|
642
|
+
{
|
643
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
644
|
+
typedef typename iterator_traits<RandIt>::value_type value_type;
|
645
|
+
size_type h = 0;
|
646
|
+
if(max_collected){
|
647
|
+
++h; // first key is always here
|
648
|
+
RandIt h0 = first;
|
649
|
+
RandIt u = first; ++u;
|
650
|
+
RandIt search_end = u;
|
651
|
+
|
652
|
+
if(xbuf.capacity() >= max_collected){
|
653
|
+
value_type *const ph0 = xbuf.add(first);
|
654
|
+
while(u != last && h < max_collected){
|
655
|
+
value_type * const r = lower_bound(ph0, xbuf.end(), *u, comp);
|
656
|
+
//If key not found add it to [h, h+h0)
|
657
|
+
if(r == xbuf.end() || comp(*u, *r) ){
|
658
|
+
RandIt const new_h0 = boost::move(search_end, u, h0);
|
659
|
+
search_end = u;
|
660
|
+
++search_end;
|
661
|
+
++h;
|
662
|
+
xbuf.insert(r, u);
|
663
|
+
h0 = new_h0;
|
664
|
+
}
|
665
|
+
++u;
|
666
|
+
}
|
667
|
+
boost::move_backward(first, h0, h0+h);
|
668
|
+
boost::move(xbuf.data(), xbuf.end(), first);
|
669
|
+
}
|
670
|
+
else{
|
671
|
+
while(u != last && h < max_collected){
|
672
|
+
RandIt const r = lower_bound(h0, search_end, *u, comp);
|
673
|
+
//If key not found add it to [h, h+h0)
|
674
|
+
if(r == search_end || comp(*u, *r) ){
|
675
|
+
RandIt const new_h0 = rotate_gcd(h0, search_end, u);
|
676
|
+
search_end = u;
|
677
|
+
++search_end;
|
678
|
+
++h;
|
679
|
+
rotate_gcd(r+(new_h0-h0), u, search_end);
|
680
|
+
h0 = new_h0;
|
681
|
+
}
|
682
|
+
++u;
|
683
|
+
}
|
684
|
+
rotate_gcd(first, h0, h0+h);
|
685
|
+
}
|
686
|
+
}
|
687
|
+
return h;
|
688
|
+
}
|
689
|
+
|
690
|
+
template<class Unsigned>
|
691
|
+
Unsigned floor_sqrt(Unsigned const n)
|
692
|
+
{
|
693
|
+
Unsigned x = n;
|
694
|
+
Unsigned y = x/2 + (x&1);
|
695
|
+
while (y < x){
|
696
|
+
x = y;
|
697
|
+
y = (x + n / x)/2;
|
698
|
+
}
|
699
|
+
return x;
|
700
|
+
}
|
701
|
+
|
702
|
+
template<class Unsigned>
|
703
|
+
Unsigned ceil_sqrt(Unsigned const n)
|
704
|
+
{
|
705
|
+
Unsigned r = floor_sqrt(n);
|
706
|
+
return r + Unsigned((n%r) != 0);
|
707
|
+
}
|
708
|
+
|
709
|
+
template<class Unsigned>
|
710
|
+
Unsigned floor_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
|
711
|
+
{
|
712
|
+
Unsigned s = n;
|
713
|
+
Unsigned p = 0;
|
714
|
+
while(s > AdaptiveSortInsertionSortThreshold){
|
715
|
+
s /= 2;
|
716
|
+
++p;
|
717
|
+
}
|
718
|
+
base = s;
|
719
|
+
pow = p;
|
720
|
+
return s << p;
|
721
|
+
}
|
722
|
+
|
723
|
+
template<class Unsigned>
|
724
|
+
Unsigned ceil_merge_multiple(Unsigned const n, Unsigned &base, Unsigned &pow)
|
725
|
+
{
|
726
|
+
Unsigned fm = floor_merge_multiple(n, base, pow);
|
727
|
+
|
728
|
+
if(fm != n){
|
729
|
+
if(base < AdaptiveSortInsertionSortThreshold){
|
730
|
+
++base;
|
731
|
+
}
|
732
|
+
else{
|
733
|
+
base = AdaptiveSortInsertionSortThreshold/2 + 1;
|
734
|
+
++pow;
|
735
|
+
}
|
736
|
+
}
|
737
|
+
return base << pow;
|
738
|
+
}
|
739
|
+
|
740
|
+
template<class Unsigned>
|
741
|
+
Unsigned ceil_sqrt_multiple(Unsigned const n, Unsigned *pbase = 0)
|
742
|
+
{
|
743
|
+
Unsigned const r = ceil_sqrt(n);
|
744
|
+
Unsigned pow = 0;
|
745
|
+
Unsigned base = 0;
|
746
|
+
Unsigned const res = ceil_merge_multiple(r, base, pow);
|
747
|
+
if(pbase) *pbase = base;
|
748
|
+
return res;
|
749
|
+
}
|
750
|
+
|
751
|
+
struct less
|
752
|
+
{
|
753
|
+
template<class T>
|
754
|
+
bool operator()(const T &l, const T &r)
|
755
|
+
{ return l < r; }
|
756
|
+
};
|
757
|
+
|
758
|
+
///////////////////////////////////////////////////////////////////////////////
|
759
|
+
//
|
760
|
+
// MERGE BLOCKS
|
761
|
+
//
|
762
|
+
///////////////////////////////////////////////////////////////////////////////
|
763
|
+
|
764
|
+
//#define ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
|
765
|
+
|
766
|
+
#if defined ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
|
767
|
+
template<class RandIt, class Compare>
|
768
|
+
void slow_stable_sort
|
769
|
+
( RandIt const first, RandIt const last, Compare comp)
|
770
|
+
{
|
771
|
+
boost::movelib::inplace_stable_sort(first, last, comp);
|
772
|
+
}
|
773
|
+
|
774
|
+
#else //ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
|
775
|
+
|
776
|
+
template<class RandIt, class Compare>
|
777
|
+
void slow_stable_sort
|
778
|
+
( RandIt const first, RandIt const last, Compare comp)
|
779
|
+
{
|
780
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
781
|
+
size_type L = size_type(last - first);
|
782
|
+
{ //Use insertion sort to merge first elements
|
783
|
+
size_type m = 0;
|
784
|
+
while((L - m) > size_type(AdaptiveSortInsertionSortThreshold)){
|
785
|
+
insertion_sort(first+m, first+m+size_type(AdaptiveSortInsertionSortThreshold), comp);
|
786
|
+
m += AdaptiveSortInsertionSortThreshold;
|
787
|
+
}
|
788
|
+
insertion_sort(first+m, last, comp);
|
789
|
+
}
|
790
|
+
|
791
|
+
size_type h = AdaptiveSortInsertionSortThreshold;
|
792
|
+
for(bool do_merge = L > h; do_merge; h*=2){
|
793
|
+
do_merge = (L - h) > h;
|
794
|
+
size_type p0 = 0;
|
795
|
+
if(do_merge){
|
796
|
+
size_type const h_2 = 2*h;
|
797
|
+
while((L-p0) > h_2){
|
798
|
+
merge_bufferless(first+p0, first+p0+h, first+p0+h_2, comp);
|
799
|
+
p0 += h_2;
|
800
|
+
}
|
801
|
+
}
|
802
|
+
if((L-p0) > h){
|
803
|
+
merge_bufferless(first+p0, first+p0+h, last, comp);
|
804
|
+
}
|
805
|
+
}
|
806
|
+
}
|
807
|
+
|
808
|
+
#endif //ADAPTIVE_SORT_MERGE_SLOW_STABLE_SORT_IS_NLOGN
|
809
|
+
|
810
|
+
//Returns new l_block and updates use_buf
|
811
|
+
template<class Unsigned>
|
812
|
+
Unsigned lblock_for_combine
|
813
|
+
(Unsigned const l_block, Unsigned const n_keys, Unsigned const l_data, bool &use_buf)
|
814
|
+
{
|
815
|
+
BOOST_ASSERT(l_data > 1);
|
816
|
+
|
817
|
+
//We need to guarantee lblock >= l_merged/(n_keys/2) keys for the combination.
|
818
|
+
//We have at least 4 keys guaranteed (which are the minimum to merge 2 ranges)
|
819
|
+
//If l_block != 0, then n_keys is already enough to merge all blocks in all
|
820
|
+
//phases as we've found all needed keys for that buffer and length before.
|
821
|
+
//If l_block == 0 then see if half keys can be used as buffer and the rest
|
822
|
+
//as keys guaranteeing that n_keys >= (2*l_merged)/lblock =
|
823
|
+
if(!l_block){
|
824
|
+
//If l_block == 0 then n_keys is power of two
|
825
|
+
//(guaranteed by build_params(...))
|
826
|
+
BOOST_ASSERT(n_keys >= 4);
|
827
|
+
//BOOST_ASSERT(0 == (n_keys &(n_keys-1)));
|
828
|
+
|
829
|
+
//See if half keys are at least 4 and if half keys fulfill
|
830
|
+
Unsigned const new_buf = n_keys/2;
|
831
|
+
Unsigned const new_keys = n_keys-new_buf;
|
832
|
+
use_buf = new_keys >= 4 && new_keys >= l_data/new_buf;
|
833
|
+
if(use_buf){
|
834
|
+
return new_buf;
|
835
|
+
}
|
836
|
+
else{
|
837
|
+
return l_data/n_keys;
|
838
|
+
}
|
839
|
+
}
|
840
|
+
else{
|
841
|
+
use_buf = true;
|
842
|
+
return l_block;
|
843
|
+
}
|
844
|
+
}
|
845
|
+
|
846
|
+
template<class RandIt, class Compare, class XBuf>
|
847
|
+
void stable_sort( RandIt first, RandIt last, Compare comp, XBuf & xbuf)
|
848
|
+
{
|
849
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
850
|
+
size_type const len = size_type(last - first);
|
851
|
+
size_type const half_len = len/2 + (len&1);
|
852
|
+
if(std::size_t(xbuf.capacity() - xbuf.size()) >= half_len) {
|
853
|
+
merge_sort(first, last, comp, xbuf.data()+xbuf.size());
|
854
|
+
}
|
855
|
+
else{
|
856
|
+
slow_stable_sort(first, last, comp);
|
857
|
+
}
|
858
|
+
}
|
859
|
+
|
860
|
+
template<class RandIt, class Comp, class XBuf>
|
861
|
+
void initialize_keys( RandIt first, RandIt last
|
862
|
+
, Comp comp
|
863
|
+
, XBuf & xbuf)
|
864
|
+
{
|
865
|
+
stable_sort(first, last, comp, xbuf);
|
866
|
+
}
|
867
|
+
|
868
|
+
template<class RandIt, class U>
|
869
|
+
void initialize_keys( RandIt first, RandIt last
|
870
|
+
, less
|
871
|
+
, U &)
|
872
|
+
{
|
873
|
+
typedef typename iterator_traits<RandIt>::value_type value_type;
|
874
|
+
std::size_t count = std::size_t(last - first);
|
875
|
+
for(std::size_t i = 0; i != count; ++i){
|
876
|
+
*first = value_type(i);
|
877
|
+
++first;
|
878
|
+
}
|
879
|
+
}
|
880
|
+
|
881
|
+
template<class RandIt>
|
882
|
+
void move_data_backward( RandIt cur_pos
|
883
|
+
, typename iterator_traits<RandIt>::size_type const l_data
|
884
|
+
, RandIt new_pos
|
885
|
+
, bool const xbuf_used)
|
886
|
+
{
|
887
|
+
//Move buffer to the total combination right
|
888
|
+
if(xbuf_used){
|
889
|
+
boost::move_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
|
890
|
+
}
|
891
|
+
else{
|
892
|
+
boost::adl_move_swap_ranges_backward(cur_pos, cur_pos+l_data, new_pos+l_data);
|
893
|
+
//Rotate does less moves but it seems slower due to cache issues
|
894
|
+
//rotate_gcd(first-l_block, first+len-l_block, first+len);
|
895
|
+
}
|
896
|
+
}
|
897
|
+
|
898
|
+
template<class RandIt>
|
899
|
+
void move_data_forward( RandIt cur_pos
|
900
|
+
, typename iterator_traits<RandIt>::size_type const l_data
|
901
|
+
, RandIt new_pos
|
902
|
+
, bool const xbuf_used)
|
903
|
+
{
|
904
|
+
//Move buffer to the total combination right
|
905
|
+
if(xbuf_used){
|
906
|
+
boost::move(cur_pos, cur_pos+l_data, new_pos);
|
907
|
+
}
|
908
|
+
else{
|
909
|
+
boost::adl_move_swap_ranges(cur_pos, cur_pos+l_data, new_pos);
|
910
|
+
//Rotate does less moves but it seems slower due to cache issues
|
911
|
+
//rotate_gcd(first-l_block, first+len-l_block, first+len);
|
912
|
+
}
|
913
|
+
}
|
914
|
+
|
915
|
+
template <class Unsigned>
|
916
|
+
Unsigned calculate_total_combined(Unsigned const len, Unsigned const l_prev_merged, Unsigned *pl_irreg_combined = 0)
|
917
|
+
{
|
918
|
+
typedef Unsigned size_type;
|
919
|
+
|
920
|
+
size_type const l_combined = 2*l_prev_merged;
|
921
|
+
size_type l_irreg_combined = len%l_combined;
|
922
|
+
size_type l_total_combined = len;
|
923
|
+
if(l_irreg_combined <= l_prev_merged){
|
924
|
+
l_total_combined -= l_irreg_combined;
|
925
|
+
l_irreg_combined = 0;
|
926
|
+
}
|
927
|
+
if(pl_irreg_combined)
|
928
|
+
*pl_irreg_combined = l_irreg_combined;
|
929
|
+
return l_total_combined;
|
930
|
+
}
|
931
|
+
|
932
|
+
template<class RandItKeys, class KeyCompare, class SizeType, class XBuf>
|
933
|
+
void combine_params
|
934
|
+
( RandItKeys const keys
|
935
|
+
, KeyCompare key_comp
|
936
|
+
, SizeType l_combined
|
937
|
+
, SizeType const l_prev_merged
|
938
|
+
, SizeType const l_block
|
939
|
+
, XBuf & xbuf
|
940
|
+
//Output
|
941
|
+
, SizeType &n_block_a
|
942
|
+
, SizeType &n_block_b
|
943
|
+
, SizeType &l_irreg1
|
944
|
+
, SizeType &l_irreg2
|
945
|
+
//Options
|
946
|
+
, bool do_initialize_keys = true)
|
947
|
+
{
|
948
|
+
typedef SizeType size_type;
|
949
|
+
|
950
|
+
//Initial parameters for selection sort blocks
|
951
|
+
l_irreg1 = l_prev_merged%l_block;
|
952
|
+
l_irreg2 = (l_combined-l_irreg1)%l_block;
|
953
|
+
BOOST_ASSERT(((l_combined-l_irreg1-l_irreg2)%l_block) == 0);
|
954
|
+
size_type const n_reg_block = (l_combined-l_irreg1-l_irreg2)/l_block;
|
955
|
+
n_block_a = l_prev_merged/l_block;
|
956
|
+
n_block_b = n_reg_block - n_block_a;
|
957
|
+
BOOST_ASSERT(n_reg_block>=n_block_a);
|
958
|
+
|
959
|
+
//Key initialization
|
960
|
+
if (do_initialize_keys) {
|
961
|
+
initialize_keys(keys, keys + needed_keys_count(n_block_a, n_block_b), key_comp, xbuf);
|
962
|
+
}
|
963
|
+
}
|
964
|
+
|
965
|
+
template<class RandIt1, class RandIt2, class RandItB, class Compare, class Op>
|
966
|
+
RandItB op_buffered_partial_merge_and_swap_to_range1_and_buffer
|
967
|
+
( RandIt1 first1, RandIt1 const last1
|
968
|
+
, RandIt2 &rfirst2, RandIt2 const last2, RandIt2 &rfirst_min
|
969
|
+
, RandItB &rfirstb, Compare comp, Op op )
|
970
|
+
{
|
971
|
+
RandItB firstb = rfirstb;
|
972
|
+
RandItB lastb = firstb;
|
973
|
+
RandIt2 first2 = rfirst2;
|
974
|
+
|
975
|
+
//Move to buffer while merging
|
976
|
+
//Three way moves need less moves when op is swap_op so use it
|
977
|
+
//when merging elements from range2 to the destination occupied by range1
|
978
|
+
if(first1 != last1 && first2 != last2){
|
979
|
+
RandIt2 first_min = rfirst_min;
|
980
|
+
op(four_way_t(), first2++, first_min++, first1++, lastb++);
|
981
|
+
|
982
|
+
while(first1 != last1){
|
983
|
+
if(first2 == last2){
|
984
|
+
lastb = op(forward_t(), first1, last1, firstb);
|
985
|
+
break;
|
986
|
+
}
|
987
|
+
bool const min_less = comp(*first_min, *firstb);
|
988
|
+
|
989
|
+
if(min_less){
|
990
|
+
op( four_way_t(), first2++, first_min++, first1++, lastb++);
|
991
|
+
}
|
992
|
+
else{
|
993
|
+
op(three_way_t(), firstb++, first1++, lastb++);
|
994
|
+
}
|
995
|
+
}
|
996
|
+
rfirst2 = first2;
|
997
|
+
rfirstb = firstb;
|
998
|
+
rfirst_min = first_min;
|
999
|
+
}
|
1000
|
+
|
1001
|
+
return lastb;
|
1002
|
+
}
|
1003
|
+
|
1004
|
+
//////////////////////////////////
|
1005
|
+
//
|
1006
|
+
// partial_merge
|
1007
|
+
//
|
1008
|
+
//////////////////////////////////
|
1009
|
+
template<class InputIt1, class InputIt2, class OutputIt, class Compare, class Op>
|
1010
|
+
OutputIt op_partial_merge_impl
|
1011
|
+
(InputIt1 &r_first1, InputIt1 const last1, InputIt2 &r_first2, InputIt2 const last2, OutputIt d_first, Compare comp, Op op)
|
1012
|
+
{
|
1013
|
+
InputIt1 first1(r_first1);
|
1014
|
+
InputIt2 first2(r_first2);
|
1015
|
+
if(first2 != last2 && last1 != first1)
|
1016
|
+
while(1){
|
1017
|
+
if(comp(*first2, *first1)) {
|
1018
|
+
op(first2++, d_first++);
|
1019
|
+
if(first2 == last2){
|
1020
|
+
break;
|
1021
|
+
}
|
1022
|
+
}
|
1023
|
+
else{
|
1024
|
+
op(first1++, d_first++);
|
1025
|
+
if(first1 == last1){
|
1026
|
+
break;
|
1027
|
+
}
|
1028
|
+
}
|
1029
|
+
}
|
1030
|
+
r_first1 = first1;
|
1031
|
+
r_first2 = first2;
|
1032
|
+
return d_first;
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
template<class InputIt1, class InputIt2, class OutputIt, class Compare, class Op>
|
1036
|
+
OutputIt op_partial_merge
|
1037
|
+
(InputIt1 &r_first1, InputIt1 const last1, InputIt2 &r_first2, InputIt2 const last2, OutputIt d_first, Compare comp, Op op, bool is_stable)
|
1038
|
+
{
|
1039
|
+
return is_stable ? op_partial_merge_impl(r_first1, last1, r_first2, last2, d_first, comp, op)
|
1040
|
+
: op_partial_merge_impl(r_first1, last1, r_first2, last2, d_first, antistable<Compare>(comp), op);
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
//////////////////////////////////
|
1044
|
+
//
|
1045
|
+
// partial_merge_and_swap
|
1046
|
+
//
|
1047
|
+
//////////////////////////////////
|
1048
|
+
template<class InputIt1, class InputIt2, class OutputIt, class Compare, class Op>
|
1049
|
+
OutputIt op_partial_merge_and_swap_impl
|
1050
|
+
(InputIt1 &r_first1, InputIt1 const last1, InputIt2 &r_first2, InputIt2 const last2, InputIt2 &r_first_min, OutputIt d_first, Compare comp, Op op)
|
1051
|
+
{
|
1052
|
+
InputIt1 first1(r_first1);
|
1053
|
+
InputIt2 first2(r_first2);
|
1054
|
+
|
1055
|
+
if(first2 != last2 && last1 != first1) {
|
1056
|
+
InputIt2 first_min(r_first_min);
|
1057
|
+
bool non_empty_ranges = true;
|
1058
|
+
do{
|
1059
|
+
if(comp(*first_min, *first1)) {
|
1060
|
+
op(three_way_t(), first2++, first_min++, d_first++);
|
1061
|
+
non_empty_ranges = first2 != last2;
|
1062
|
+
}
|
1063
|
+
else{
|
1064
|
+
op(first1++, d_first++);
|
1065
|
+
non_empty_ranges = first1 != last1;
|
1066
|
+
}
|
1067
|
+
} while(non_empty_ranges);
|
1068
|
+
r_first_min = first_min;
|
1069
|
+
r_first1 = first1;
|
1070
|
+
r_first2 = first2;
|
1071
|
+
}
|
1072
|
+
return d_first;
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
template<class RandIt, class InputIt2, class OutputIt, class Compare, class Op>
|
1076
|
+
RandIt op_partial_merge_and_swap
|
1077
|
+
(RandIt &r_first1, RandIt const last1, RandIt &r_first2, RandIt const last2, InputIt2 &r_first_min, OutputIt d_first, Compare comp, Op op, bool is_stable)
|
1078
|
+
{
|
1079
|
+
return is_stable ? op_partial_merge_and_swap_impl(r_first1, last1, r_first2, last2, r_first_min, d_first, comp, op)
|
1080
|
+
: op_partial_merge_and_swap_impl(r_first1, last1, r_first2, last2, r_first_min, d_first, antistable<Compare>(comp), op);
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
template<class RandIt, class RandItBuf, class Compare, class Op>
|
1084
|
+
RandIt op_partial_merge_and_save_impl
|
1085
|
+
( RandIt first1, RandIt const last1, RandIt &rfirst2, RandIt last2, RandIt first_min
|
1086
|
+
, RandItBuf &buf_first1_in_out, RandItBuf &buf_last1_in_out
|
1087
|
+
, Compare comp, Op op
|
1088
|
+
)
|
1089
|
+
{
|
1090
|
+
RandItBuf buf_first1 = buf_first1_in_out;
|
1091
|
+
RandItBuf buf_last1 = buf_last1_in_out;
|
1092
|
+
RandIt first2(rfirst2);
|
1093
|
+
|
1094
|
+
bool const do_swap = first2 != first_min;
|
1095
|
+
if(buf_first1 == buf_last1){
|
1096
|
+
//Skip any element that does not need to be moved
|
1097
|
+
RandIt new_first1 = skip_until_merge(first1, last1, *first_min, comp);
|
1098
|
+
buf_first1 += (new_first1-first1);
|
1099
|
+
first1 = new_first1;
|
1100
|
+
buf_last1 = do_swap ? op_buffered_partial_merge_and_swap_to_range1_and_buffer(first1, last1, first2, last2, first_min, buf_first1, comp, op)
|
1101
|
+
: op_buffered_partial_merge_to_range1_and_buffer (first1, last1, first2, last2, buf_first1, comp, op);
|
1102
|
+
first1 = last1;
|
1103
|
+
}
|
1104
|
+
else{
|
1105
|
+
BOOST_ASSERT((last1-first1) == (buf_last1 - buf_first1));
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
//Now merge from buffer
|
1109
|
+
first1 = do_swap ? op_partial_merge_and_swap_impl(buf_first1, buf_last1, first2, last2, first_min, first1, comp, op)
|
1110
|
+
: op_partial_merge_impl (buf_first1, buf_last1, first2, last2, first1, comp, op);
|
1111
|
+
buf_first1_in_out = buf_first1;
|
1112
|
+
buf_last1_in_out = buf_last1;
|
1113
|
+
rfirst2 = first2;
|
1114
|
+
return first1;
|
1115
|
+
}
|
1116
|
+
|
1117
|
+
template<class RandIt, class RandItBuf, class Compare, class Op>
|
1118
|
+
RandIt op_partial_merge_and_save
|
1119
|
+
( RandIt first1, RandIt const last1, RandIt &rfirst2, RandIt last2, RandIt first_min
|
1120
|
+
, RandItBuf &buf_first1_in_out
|
1121
|
+
, RandItBuf &buf_last1_in_out
|
1122
|
+
, Compare comp
|
1123
|
+
, Op op
|
1124
|
+
, bool is_stable)
|
1125
|
+
{
|
1126
|
+
return is_stable
|
1127
|
+
? op_partial_merge_and_save_impl
|
1128
|
+
(first1, last1, rfirst2, last2, first_min, buf_first1_in_out, buf_last1_in_out, comp, op)
|
1129
|
+
: op_partial_merge_and_save_impl
|
1130
|
+
(first1, last1, rfirst2, last2, first_min, buf_first1_in_out, buf_last1_in_out, antistable<Compare>(comp), op)
|
1131
|
+
;
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
|
1135
|
+
|
1136
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class RandIt2, class OutputIt, class Compare, class Op>
|
1137
|
+
OutputIt op_merge_blocks_with_irreg
|
1138
|
+
( RandItKeys key_first
|
1139
|
+
, RandItKeys key_mid
|
1140
|
+
, KeyCompare key_comp
|
1141
|
+
, RandIt first_reg
|
1142
|
+
, RandIt2 &first_irr
|
1143
|
+
, RandIt2 const last_irr
|
1144
|
+
, OutputIt dest
|
1145
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
1146
|
+
, typename iterator_traits<RandIt>::size_type n_block_left
|
1147
|
+
, typename iterator_traits<RandIt>::size_type min_check
|
1148
|
+
, typename iterator_traits<RandIt>::size_type max_check
|
1149
|
+
, Compare comp, bool const is_stable, Op op)
|
1150
|
+
{
|
1151
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1152
|
+
|
1153
|
+
for(; n_block_left; --n_block_left, ++key_first, min_check -= min_check != 0, max_check -= max_check != 0){
|
1154
|
+
size_type next_key_idx = find_next_block(key_first, key_comp, first_reg, l_block, min_check, max_check, comp);
|
1155
|
+
max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
|
1156
|
+
RandIt const last_reg = first_reg + l_block;
|
1157
|
+
RandIt first_min = first_reg + next_key_idx*l_block;
|
1158
|
+
RandIt const last_min = first_min + l_block; (void)last_min;
|
1159
|
+
|
1160
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_reg, last_reg, comp));
|
1161
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!next_key_idx || is_sorted(first_min, last_min, comp));
|
1162
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((!next_key_idx || !comp(*first_reg, *first_min )));
|
1163
|
+
|
1164
|
+
OutputIt orig_dest = dest; (void)orig_dest;
|
1165
|
+
dest = next_key_idx ? op_partial_merge_and_swap(first_irr, last_irr, first_reg, last_reg, first_min, dest, comp, op, is_stable)
|
1166
|
+
: op_partial_merge (first_irr, last_irr, first_reg, last_reg, dest, comp, op, is_stable);
|
1167
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(orig_dest, dest, comp));
|
1168
|
+
|
1169
|
+
if(first_reg == dest){
|
1170
|
+
dest = next_key_idx ? ::boost::adl_move_swap_ranges(first_min, last_min, first_reg)
|
1171
|
+
: last_reg;
|
1172
|
+
}
|
1173
|
+
else{
|
1174
|
+
dest = next_key_idx ? op(three_way_forward_t(), first_reg, last_reg, first_min, dest)
|
1175
|
+
: op(forward_t(), first_reg, last_reg, dest);
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
RandItKeys const key_next(key_first + next_key_idx);
|
1179
|
+
swap_and_update_key(next_key_idx != 0, key_next, key_first, key_mid, last_reg, last_reg, first_min);
|
1180
|
+
|
1181
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(orig_dest, dest, comp));
|
1182
|
+
first_reg = last_reg;
|
1183
|
+
}
|
1184
|
+
return dest;
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Op>
|
1188
|
+
void op_merge_blocks_left
|
1189
|
+
( RandItKeys const key_first
|
1190
|
+
, KeyCompare key_comp
|
1191
|
+
, RandIt const first
|
1192
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
1193
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg1
|
1194
|
+
, typename iterator_traits<RandIt>::size_type const n_block_a
|
1195
|
+
, typename iterator_traits<RandIt>::size_type const n_block_b
|
1196
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg2
|
1197
|
+
, Compare comp, Op op)
|
1198
|
+
{
|
1199
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1200
|
+
size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
|
1201
|
+
// BOOST_ASSERT(n_block_a || n_block_b);
|
1202
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted_and_unique(key_first, key_first + key_count, key_comp));
|
1203
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
|
1204
|
+
|
1205
|
+
size_type n_block_b_left = n_block_b;
|
1206
|
+
size_type n_block_a_left = n_block_a;
|
1207
|
+
size_type n_block_left = n_block_b + n_block_a;
|
1208
|
+
RandItKeys key_mid(key_first + n_block_a);
|
1209
|
+
|
1210
|
+
RandIt buffer = first - l_block;
|
1211
|
+
RandIt first1 = first;
|
1212
|
+
RandIt last1 = first1 + l_irreg1;
|
1213
|
+
RandIt first2 = last1;
|
1214
|
+
RandIt const irreg2 = first2 + n_block_left*l_block;
|
1215
|
+
bool is_range1_A = true;
|
1216
|
+
|
1217
|
+
RandItKeys key_range2(key_first);
|
1218
|
+
|
1219
|
+
////////////////////////////////////////////////////////////////////////////
|
1220
|
+
//Process all regular blocks before the irregular B block
|
1221
|
+
////////////////////////////////////////////////////////////////////////////
|
1222
|
+
size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
|
1223
|
+
size_type max_check = min_value(min_check+1, n_block_left);
|
1224
|
+
for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) {
|
1225
|
+
size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp);
|
1226
|
+
max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
|
1227
|
+
RandIt const first_min = first2 + next_key_idx*l_block;
|
1228
|
+
RandIt const last_min = first_min + l_block; (void)last_min;
|
1229
|
+
RandIt const last2 = first2 + l_block;
|
1230
|
+
|
1231
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first1, last1, comp));
|
1232
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp));
|
1233
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || is_sorted(first_min, last_min, comp));
|
1234
|
+
|
1235
|
+
//Check if irregular b block should go here.
|
1236
|
+
//If so, break to the special code handling the irregular block
|
1237
|
+
if (!n_block_b_left &&
|
1238
|
+
( (l_irreg2 && comp(*irreg2, *first_min)) || (!l_irreg2 && is_range1_A)) ){
|
1239
|
+
break;
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
RandItKeys const key_next(key_range2 + next_key_idx);
|
1243
|
+
bool const is_range2_A = key_mid == (key_first+key_count) || key_comp(*key_next, *key_mid);
|
1244
|
+
|
1245
|
+
bool const is_buffer_middle = last1 == buffer;
|
1246
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT( ( is_buffer_middle && size_type(first2-buffer) == l_block && buffer == last1) ||
|
1247
|
+
(!is_buffer_middle && size_type(first1-buffer) == l_block && first2 == last1));
|
1248
|
+
|
1249
|
+
if(is_range1_A == is_range2_A){
|
1250
|
+
BOOST_ASSERT((first1 == last1) || !comp(*first_min, last1[-1]));
|
1251
|
+
if(!is_buffer_middle){
|
1252
|
+
buffer = op(forward_t(), first1, last1, buffer);
|
1253
|
+
}
|
1254
|
+
swap_and_update_key(next_key_idx != 0, key_next, key_range2, key_mid, first2, last2, first_min);
|
1255
|
+
first1 = first2;
|
1256
|
+
last1 = last2;
|
1257
|
+
}
|
1258
|
+
else {
|
1259
|
+
RandIt unmerged;
|
1260
|
+
RandIt buf_beg;
|
1261
|
+
RandIt buf_end;
|
1262
|
+
if(is_buffer_middle){
|
1263
|
+
buf_end = buf_beg = first2 - (last1-first1);
|
1264
|
+
unmerged = op_partial_merge_and_save( first1, last1, first2, last2, first_min
|
1265
|
+
, buf_beg, buf_end, comp, op, is_range1_A);
|
1266
|
+
}
|
1267
|
+
else{
|
1268
|
+
buf_beg = first1;
|
1269
|
+
buf_end = last1;
|
1270
|
+
unmerged = op_partial_merge_and_save
|
1271
|
+
(buffer, buffer+(last1-first1), first2, last2, first_min, buf_beg, buf_end, comp, op, is_range1_A);
|
1272
|
+
}
|
1273
|
+
(void)unmerged;
|
1274
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, unmerged, comp));
|
1275
|
+
|
1276
|
+
swap_and_update_key( next_key_idx != 0, key_next, key_range2, key_mid, first2, last2
|
1277
|
+
, last_min - size_type(last2 - first2));
|
1278
|
+
|
1279
|
+
if(buf_beg != buf_end){ //range2 exhausted: is_buffer_middle for the next iteration
|
1280
|
+
first1 = buf_beg;
|
1281
|
+
last1 = buf_end;
|
1282
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(buf_end == (last2-l_block));
|
1283
|
+
buffer = last1;
|
1284
|
+
}
|
1285
|
+
else{ //range1 exhausted: !is_buffer_middle for the next iteration
|
1286
|
+
first1 = first2;
|
1287
|
+
last1 = last2;
|
1288
|
+
buffer = first2 - l_block;
|
1289
|
+
is_range1_A = is_range2_A;
|
1290
|
+
}
|
1291
|
+
}
|
1292
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left));
|
1293
|
+
is_range2_A ? --n_block_a_left : --n_block_b_left;
|
1294
|
+
first2 = last2;
|
1295
|
+
}
|
1296
|
+
|
1297
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_range2 + n_block_left, key_comp, *key_mid));
|
1298
|
+
BOOST_ASSERT(!n_block_b_left);
|
1299
|
+
|
1300
|
+
////////////////////////////////////////////////////////////////////////////
|
1301
|
+
//Process remaining range 1 left before the irregular B block
|
1302
|
+
////////////////////////////////////////////////////////////////////////////
|
1303
|
+
bool const is_buffer_middle = last1 == buffer;
|
1304
|
+
RandIt first_irr2 = irreg2;
|
1305
|
+
RandIt const last_irr2 = first_irr2 + l_irreg2;
|
1306
|
+
if(l_irreg2 && is_range1_A){
|
1307
|
+
if(is_buffer_middle){
|
1308
|
+
first1 = skip_until_merge(first1, last1, *first_irr2, comp);
|
1309
|
+
//Even if we copy backward, no overlapping occurs so use forward copy
|
1310
|
+
//that can be faster specially with trivial types
|
1311
|
+
RandIt const new_first1 = first2 - (last1 - first1);
|
1312
|
+
op(forward_t(), first1, last1, new_first1);
|
1313
|
+
first1 = new_first1;
|
1314
|
+
last1 = first2;
|
1315
|
+
buffer = first1 - l_block;
|
1316
|
+
}
|
1317
|
+
buffer = op_partial_merge_impl(first1, last1, first_irr2, last_irr2, buffer, comp, op);
|
1318
|
+
buffer = op(forward_t(), first1, last1, buffer);
|
1319
|
+
}
|
1320
|
+
else if(!is_buffer_middle){
|
1321
|
+
buffer = op(forward_t(), first1, last1, buffer);
|
1322
|
+
}
|
1323
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, buffer, comp));
|
1324
|
+
|
1325
|
+
////////////////////////////////////////////////////////////////////////////
|
1326
|
+
//Process irregular B block and remaining A blocks
|
1327
|
+
////////////////////////////////////////////////////////////////////////////
|
1328
|
+
buffer = op_merge_blocks_with_irreg
|
1329
|
+
( key_range2, key_mid, key_comp, first2, first_irr2, last_irr2
|
1330
|
+
, buffer, l_block, n_block_left, min_check, max_check, comp, false, op);
|
1331
|
+
buffer = op(forward_t(), first_irr2, last_irr2, buffer);(void)buffer;
|
1332
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first-l_block, buffer, comp));
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
// first - first element to merge.
|
1336
|
+
// first[-l_block, 0) - buffer (if use_buf == true)
|
1337
|
+
// l_block - length of regular blocks. First nblocks are stable sorted by 1st elements and key-coded
|
1338
|
+
// keys - sequence of keys, in same order as blocks. key<midkey means stream A
|
1339
|
+
// n_bef_irreg2/n_aft_irreg2 are regular blocks
|
1340
|
+
// l_irreg2 is a irregular block, that is to be combined after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
|
1341
|
+
// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
|
1342
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
|
1343
|
+
void merge_blocks_left
|
1344
|
+
( RandItKeys const key_first
|
1345
|
+
, KeyCompare key_comp
|
1346
|
+
, RandIt const first
|
1347
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
1348
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg1
|
1349
|
+
, typename iterator_traits<RandIt>::size_type const n_block_a
|
1350
|
+
, typename iterator_traits<RandIt>::size_type const n_block_b
|
1351
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg2
|
1352
|
+
, Compare comp
|
1353
|
+
, bool const xbuf_used)
|
1354
|
+
{
|
1355
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + needed_keys_count(n_block_a, n_block_b), key_comp, key_first[n_block_a]));
|
1356
|
+
if(xbuf_used){
|
1357
|
+
op_merge_blocks_left
|
1358
|
+
(key_first, key_comp, first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, move_op());
|
1359
|
+
}
|
1360
|
+
else{
|
1361
|
+
op_merge_blocks_left
|
1362
|
+
(key_first, key_comp, first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, swap_op());
|
1363
|
+
}
|
1364
|
+
}
|
1365
|
+
|
1366
|
+
|
1367
|
+
// first - first element to merge.
|
1368
|
+
// [first+l_block*(n_bef_irreg2+n_aft_irreg2)+l_irreg2, first+l_block*(n_bef_irreg2+n_aft_irreg2+1)+l_irreg2) - buffer
|
1369
|
+
// l_block - length of regular blocks. First nblocks are stable sorted by 1st elements and key-coded
|
1370
|
+
// keys - sequence of keys, in same order as blocks. key<midkey means stream A
|
1371
|
+
// n_bef_irreg2/n_aft_irreg2 are regular blocks
|
1372
|
+
// l_irreg2 is a irregular block, that is to be combined after n_bef_irreg2 blocks and before n_aft_irreg2 blocks
|
1373
|
+
// If l_irreg2==0 then n_aft_irreg2==0 (no irregular blocks).
|
1374
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare>
|
1375
|
+
void merge_blocks_right
|
1376
|
+
( RandItKeys const key_first
|
1377
|
+
, KeyCompare key_comp
|
1378
|
+
, RandIt const first
|
1379
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
1380
|
+
, typename iterator_traits<RandIt>::size_type const n_block_a
|
1381
|
+
, typename iterator_traits<RandIt>::size_type const n_block_b
|
1382
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg2
|
1383
|
+
, Compare comp
|
1384
|
+
, bool const xbuf_used)
|
1385
|
+
{
|
1386
|
+
merge_blocks_left
|
1387
|
+
( make_reverse_iterator(key_first + needed_keys_count(n_block_a, n_block_b))
|
1388
|
+
, inverse<KeyCompare>(key_comp)
|
1389
|
+
, make_reverse_iterator(first + ((n_block_a+n_block_b)*l_block+l_irreg2))
|
1390
|
+
, l_block
|
1391
|
+
, l_irreg2
|
1392
|
+
, n_block_b
|
1393
|
+
, n_block_a
|
1394
|
+
, 0
|
1395
|
+
, inverse<Compare>(comp), xbuf_used);
|
1396
|
+
}
|
1397
|
+
|
1398
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class Op, class RandItBuf>
|
1399
|
+
void op_merge_blocks_with_buf
|
1400
|
+
( RandItKeys key_first
|
1401
|
+
, KeyCompare key_comp
|
1402
|
+
, RandIt const first
|
1403
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
1404
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg1
|
1405
|
+
, typename iterator_traits<RandIt>::size_type const n_block_a
|
1406
|
+
, typename iterator_traits<RandIt>::size_type const n_block_b
|
1407
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg2
|
1408
|
+
, Compare comp
|
1409
|
+
, Op op
|
1410
|
+
, RandItBuf const buf_first)
|
1411
|
+
{
|
1412
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1413
|
+
size_type const key_count = needed_keys_count(n_block_a, n_block_b); (void)key_count;
|
1414
|
+
//BOOST_ASSERT(n_block_a || n_block_b);
|
1415
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted_and_unique(key_first, key_first + key_count, key_comp));
|
1416
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_b || n_block_a == count_if_with(key_first, key_first + key_count, key_comp, key_first[n_block_a]));
|
1417
|
+
|
1418
|
+
size_type n_block_b_left = n_block_b;
|
1419
|
+
size_type n_block_a_left = n_block_a;
|
1420
|
+
size_type n_block_left = n_block_b + n_block_a;
|
1421
|
+
RandItKeys key_mid(key_first + n_block_a);
|
1422
|
+
|
1423
|
+
RandItBuf buffer = buf_first;
|
1424
|
+
RandItBuf buffer_end = buffer;
|
1425
|
+
RandIt first1 = first;
|
1426
|
+
RandIt last1 = first1 + l_irreg1;
|
1427
|
+
RandIt first2 = last1;
|
1428
|
+
RandIt const first_irr2 = first2 + n_block_left*l_block;
|
1429
|
+
bool is_range1_A = true;
|
1430
|
+
|
1431
|
+
RandItKeys key_range2(key_first);
|
1432
|
+
|
1433
|
+
////////////////////////////////////////////////////////////////////////////
|
1434
|
+
//Process all regular blocks before the irregular B block
|
1435
|
+
////////////////////////////////////////////////////////////////////////////
|
1436
|
+
size_type min_check = n_block_a == n_block_left ? 0u : n_block_a;
|
1437
|
+
size_type max_check = min_value(min_check+1, n_block_left);
|
1438
|
+
for (; n_block_left; --n_block_left, ++key_range2, min_check -= min_check != 0, max_check -= max_check != 0) {
|
1439
|
+
size_type const next_key_idx = find_next_block(key_range2, key_comp, first2, l_block, min_check, max_check, comp);
|
1440
|
+
max_check = min_value(max_value(max_check, next_key_idx+2), n_block_left);
|
1441
|
+
RandIt first_min = first2 + next_key_idx*l_block;
|
1442
|
+
RandIt const last_min = first_min + l_block; (void)last_min;
|
1443
|
+
RandIt const last2 = first2 + l_block;
|
1444
|
+
|
1445
|
+
bool const buffer_empty = buffer == buffer_end; (void)buffer_empty;
|
1446
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(buffer_empty ? is_sorted(first1, last1, comp) : is_sorted(buffer, buffer_end, comp));
|
1447
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp));
|
1448
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!n_block_left || is_sorted(first_min, last_min, comp));
|
1449
|
+
|
1450
|
+
//Check if irregular b block should go here.
|
1451
|
+
//If so, break to the special code handling the irregular block
|
1452
|
+
if (!n_block_b_left &&
|
1453
|
+
( (l_irreg2 && comp(*first_irr2, *first_min)) || (!l_irreg2 && is_range1_A)) ){
|
1454
|
+
break;
|
1455
|
+
}
|
1456
|
+
|
1457
|
+
RandItKeys const key_next(key_range2 + next_key_idx);
|
1458
|
+
bool const is_range2_A = key_mid == (key_first+key_count) || key_comp(*key_next, *key_mid);
|
1459
|
+
|
1460
|
+
if(is_range1_A == is_range2_A){
|
1461
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT((first1 == last1) || (buffer_empty ? !comp(*first_min, last1[-1]) : !comp(*first_min, buffer_end[-1])));
|
1462
|
+
//If buffered, put those elements in place
|
1463
|
+
RandIt res = op(forward_t(), buffer, buffer_end, first1);
|
1464
|
+
buffer = buffer_end = buf_first;
|
1465
|
+
BOOST_ASSERT(buffer_empty || res == last1); (void)res;
|
1466
|
+
swap_and_update_key(next_key_idx != 0, key_next, key_range2, key_mid, first2, last2, first_min);
|
1467
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first2, last2, comp));
|
1468
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, last_min, comp));
|
1469
|
+
first1 = first2;
|
1470
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, first1, comp));
|
1471
|
+
}
|
1472
|
+
else {
|
1473
|
+
RandIt const unmerged = op_partial_merge_and_save(first1, last1, first2, last2, first_min, buffer, buffer_end, comp, op, is_range1_A);
|
1474
|
+
bool const is_range_1_empty = buffer == buffer_end;
|
1475
|
+
BOOST_ASSERT(is_range_1_empty || (buffer_end-buffer) == (last1+l_block-unmerged));
|
1476
|
+
if(is_range_1_empty){
|
1477
|
+
buffer = buffer_end = buf_first;
|
1478
|
+
first_min = last_min - (last2 - first2);
|
1479
|
+
}
|
1480
|
+
else{
|
1481
|
+
first_min = last_min;
|
1482
|
+
}
|
1483
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(!is_range_1_empty || (last_min-first_min) == (last2-unmerged));
|
1484
|
+
swap_and_update_key(next_key_idx != 0, key_next, key_range2, key_mid, first2, last2, first_min);
|
1485
|
+
|
1486
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first_min, last_min, comp));
|
1487
|
+
is_range1_A ^= is_range_1_empty;
|
1488
|
+
first1 = unmerged;
|
1489
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, unmerged, comp));
|
1490
|
+
}
|
1491
|
+
BOOST_ASSERT( (is_range2_A && n_block_a_left) || (!is_range2_A && n_block_b_left));
|
1492
|
+
is_range2_A ? --n_block_a_left : --n_block_b_left;
|
1493
|
+
last1 += l_block;
|
1494
|
+
first2 = last2;
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
RandIt res = op(forward_t(), buffer, buffer_end, first1); (void)res;
|
1498
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, res, comp));
|
1499
|
+
|
1500
|
+
////////////////////////////////////////////////////////////////////////////
|
1501
|
+
//Process irregular B block and remaining A blocks
|
1502
|
+
////////////////////////////////////////////////////////////////////////////
|
1503
|
+
RandIt const last_irr2 = first_irr2 + l_irreg2;
|
1504
|
+
op(forward_t(), first_irr2, first_irr2+l_irreg2, buf_first);
|
1505
|
+
buffer = buf_first;
|
1506
|
+
buffer_end = buffer+l_irreg2;
|
1507
|
+
|
1508
|
+
reverse_iterator<RandItBuf> rbuf_beg(buffer_end);
|
1509
|
+
RandIt dest = op_merge_blocks_with_irreg
|
1510
|
+
( make_reverse_iterator(key_first + n_block_b + n_block_a), make_reverse_iterator(key_mid), inverse<KeyCompare>(key_comp)
|
1511
|
+
, make_reverse_iterator(first_irr2), rbuf_beg
|
1512
|
+
, make_reverse_iterator(buffer), make_reverse_iterator(last_irr2)
|
1513
|
+
, l_block, n_block_left, 0, n_block_left
|
1514
|
+
, inverse<Compare>(comp), true, op).base();
|
1515
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(dest, last_irr2, comp));
|
1516
|
+
|
1517
|
+
buffer_end = rbuf_beg.base();
|
1518
|
+
BOOST_ASSERT((dest-last1) == (buffer_end-buffer));
|
1519
|
+
op_merge_with_left_placed(is_range1_A ? first1 : last1, last1, dest, buffer, buffer_end, comp, op);
|
1520
|
+
|
1521
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(first, last_irr2, comp));
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class RandItBuf>
|
1525
|
+
void merge_blocks_with_buf
|
1526
|
+
( RandItKeys key_first
|
1527
|
+
, KeyCompare key_comp
|
1528
|
+
, RandIt const first
|
1529
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
1530
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg1
|
1531
|
+
, typename iterator_traits<RandIt>::size_type const n_block_a
|
1532
|
+
, typename iterator_traits<RandIt>::size_type const n_block_b
|
1533
|
+
, typename iterator_traits<RandIt>::size_type const l_irreg2
|
1534
|
+
, Compare comp
|
1535
|
+
, RandItBuf const buf_first
|
1536
|
+
, bool const xbuf_used)
|
1537
|
+
{
|
1538
|
+
if(xbuf_used){
|
1539
|
+
op_merge_blocks_with_buf
|
1540
|
+
(key_first, key_comp, first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, move_op(), buf_first);
|
1541
|
+
}
|
1542
|
+
else{
|
1543
|
+
op_merge_blocks_with_buf
|
1544
|
+
(key_first, key_comp, first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, swap_op(), buf_first);
|
1545
|
+
}
|
1546
|
+
}
|
1547
|
+
|
1548
|
+
template<class RandIt, class Compare, class Op>
|
1549
|
+
typename iterator_traits<RandIt>::size_type
|
1550
|
+
op_insertion_sort_step_left
|
1551
|
+
( RandIt const first
|
1552
|
+
, typename iterator_traits<RandIt>::size_type const length
|
1553
|
+
, typename iterator_traits<RandIt>::size_type const step
|
1554
|
+
, Compare comp, Op op)
|
1555
|
+
{
|
1556
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1557
|
+
size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
|
1558
|
+
size_type m = 0;
|
1559
|
+
|
1560
|
+
while((length - m) > s){
|
1561
|
+
insertion_sort_op(first+m, first+m+s, first+m-s, comp, op);
|
1562
|
+
m += s;
|
1563
|
+
}
|
1564
|
+
insertion_sort_op(first+m, first+length, first+m-s, comp, op);
|
1565
|
+
return s;
|
1566
|
+
}
|
1567
|
+
|
1568
|
+
template<class RandIt, class Compare>
|
1569
|
+
typename iterator_traits<RandIt>::size_type
|
1570
|
+
insertion_sort_step
|
1571
|
+
( RandIt const first
|
1572
|
+
, typename iterator_traits<RandIt>::size_type const length
|
1573
|
+
, typename iterator_traits<RandIt>::size_type const step
|
1574
|
+
, Compare comp)
|
1575
|
+
{
|
1576
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1577
|
+
size_type const s = min_value<size_type>(step, AdaptiveSortInsertionSortThreshold);
|
1578
|
+
size_type m = 0;
|
1579
|
+
|
1580
|
+
while((length - m) > s){
|
1581
|
+
insertion_sort(first+m, first+m+s, comp);
|
1582
|
+
m += s;
|
1583
|
+
}
|
1584
|
+
insertion_sort(first+m, first+length, comp);
|
1585
|
+
return s;
|
1586
|
+
}
|
1587
|
+
|
1588
|
+
template<class RandIt, class Compare, class Op>
|
1589
|
+
typename iterator_traits<RandIt>::size_type
|
1590
|
+
op_merge_left_step_multiple
|
1591
|
+
( RandIt first_block
|
1592
|
+
, typename iterator_traits<RandIt>::size_type const elements_in_blocks
|
1593
|
+
, typename iterator_traits<RandIt>::size_type l_merged
|
1594
|
+
, typename iterator_traits<RandIt>::size_type const l_build_buf
|
1595
|
+
, typename iterator_traits<RandIt>::size_type l_left_space
|
1596
|
+
, Compare comp
|
1597
|
+
, Op op)
|
1598
|
+
{
|
1599
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1600
|
+
for(; l_merged < l_build_buf && l_left_space >= l_merged; l_merged*=2){
|
1601
|
+
size_type p0=0;
|
1602
|
+
RandIt pos = first_block;
|
1603
|
+
while((elements_in_blocks - p0) > 2*l_merged) {
|
1604
|
+
op_merge_left(pos-l_merged, pos, pos+l_merged, pos+2*l_merged, comp, op);
|
1605
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, pos+l_merged, comp));
|
1606
|
+
p0 += 2*l_merged;
|
1607
|
+
pos = first_block+p0;
|
1608
|
+
}
|
1609
|
+
if((elements_in_blocks-p0) > l_merged) {
|
1610
|
+
op_merge_left(pos-l_merged, pos, pos+l_merged, first_block+elements_in_blocks, comp, op);
|
1611
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, pos-l_merged+(first_block+elements_in_blocks-pos), comp));
|
1612
|
+
}
|
1613
|
+
else {
|
1614
|
+
op(forward_t(), pos, first_block+elements_in_blocks, pos-l_merged);
|
1615
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(pos-l_merged, first_block+elements_in_blocks-l_merged, comp));
|
1616
|
+
}
|
1617
|
+
first_block -= l_merged;
|
1618
|
+
l_left_space -= l_merged;
|
1619
|
+
}
|
1620
|
+
return l_merged;
|
1621
|
+
}
|
1622
|
+
|
1623
|
+
template<class RandIt, class Compare, class Op>
|
1624
|
+
void op_merge_right_step_once
|
1625
|
+
( RandIt first_block
|
1626
|
+
, typename iterator_traits<RandIt>::size_type const elements_in_blocks
|
1627
|
+
, typename iterator_traits<RandIt>::size_type const l_build_buf
|
1628
|
+
, Compare comp
|
1629
|
+
, Op op)
|
1630
|
+
{
|
1631
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1632
|
+
size_type restk = elements_in_blocks%(2*l_build_buf);
|
1633
|
+
size_type p = elements_in_blocks - restk;
|
1634
|
+
BOOST_ASSERT(0 == (p%(2*l_build_buf)));
|
1635
|
+
|
1636
|
+
if(restk <= l_build_buf){
|
1637
|
+
op(backward_t(),first_block+p, first_block+p+restk, first_block+p+restk+l_build_buf);
|
1638
|
+
}
|
1639
|
+
else{
|
1640
|
+
op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+restk, first_block+p+restk+l_build_buf, comp, op);
|
1641
|
+
}
|
1642
|
+
while(p>0){
|
1643
|
+
p -= 2*l_build_buf;
|
1644
|
+
op_merge_right(first_block+p, first_block+p+l_build_buf, first_block+p+2*l_build_buf, first_block+p+3*l_build_buf, comp, op);
|
1645
|
+
}
|
1646
|
+
}
|
1647
|
+
|
1648
|
+
|
1649
|
+
// build blocks of length 2*l_build_buf. l_build_buf is power of two
|
1650
|
+
// input: [0, l_build_buf) elements are buffer, rest unsorted elements
|
1651
|
+
// output: [0, l_build_buf) elements are buffer, blocks 2*l_build_buf and last subblock sorted
|
1652
|
+
//
|
1653
|
+
// First elements are merged from right to left until elements start
|
1654
|
+
// at first. All old elements [first, first + l_build_buf) are placed at the end
|
1655
|
+
// [first+len-l_build_buf, first+len). To achieve this:
|
1656
|
+
// - If we have external memory to merge, we save elements from the buffer
|
1657
|
+
// so that a non-swapping merge is used. Buffer elements are restored
|
1658
|
+
// at the end of the buffer from the external memory.
|
1659
|
+
//
|
1660
|
+
// - When the external memory is not available or it is insufficient
|
1661
|
+
// for a merge operation, left swap merging is used.
|
1662
|
+
//
|
1663
|
+
// Once elements are merged left to right in blocks of l_build_buf, then a single left
|
1664
|
+
// to right merge step is performed to achieve merged blocks of size 2K.
|
1665
|
+
// If external memory is available, usual merge is used, swap merging otherwise.
|
1666
|
+
//
|
1667
|
+
// As a last step, if auxiliary memory is available in-place merge is performed.
|
1668
|
+
// until all is merged or auxiliary memory is not large enough.
|
1669
|
+
template<class RandIt, class Compare>
|
1670
|
+
typename iterator_traits<RandIt>::size_type
|
1671
|
+
adaptive_sort_build_blocks
|
1672
|
+
( RandIt const first
|
1673
|
+
, typename iterator_traits<RandIt>::size_type const len
|
1674
|
+
, typename iterator_traits<RandIt>::size_type const l_base
|
1675
|
+
, typename iterator_traits<RandIt>::size_type const l_build_buf
|
1676
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
|
1677
|
+
, Compare comp)
|
1678
|
+
{
|
1679
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1680
|
+
BOOST_ASSERT(l_build_buf <= len);
|
1681
|
+
BOOST_ASSERT(0 == ((l_build_buf / l_base)&(l_build_buf/l_base-1)));
|
1682
|
+
|
1683
|
+
//Place the start pointer after the buffer
|
1684
|
+
RandIt first_block = first + l_build_buf;
|
1685
|
+
size_type const elements_in_blocks = len - l_build_buf;
|
1686
|
+
|
1687
|
+
//////////////////////////////////
|
1688
|
+
// Start of merge to left step
|
1689
|
+
//////////////////////////////////
|
1690
|
+
size_type l_merged = 0u;
|
1691
|
+
|
1692
|
+
BOOST_ASSERT(l_build_buf);
|
1693
|
+
//If there is no enough buffer for the insertion sort step, just avoid the external buffer
|
1694
|
+
size_type kbuf = min_value<size_type>(l_build_buf, size_type(xbuf.capacity()));
|
1695
|
+
kbuf = kbuf < l_base ? 0 : kbuf;
|
1696
|
+
|
1697
|
+
if(kbuf){
|
1698
|
+
//Backup internal buffer values in external buffer so they can be overwritten
|
1699
|
+
xbuf.move_assign(first+l_build_buf-kbuf, kbuf);
|
1700
|
+
l_merged = op_insertion_sort_step_left(first_block, elements_in_blocks, l_base, comp, move_op());
|
1701
|
+
|
1702
|
+
//Now combine them using the buffer. Elements from buffer can be
|
1703
|
+
//overwritten since they've been saved to xbuf
|
1704
|
+
l_merged = op_merge_left_step_multiple
|
1705
|
+
( first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, kbuf - l_merged, comp, move_op());
|
1706
|
+
|
1707
|
+
//Restore internal buffer from external buffer unless kbuf was l_build_buf,
|
1708
|
+
//in that case restoration will happen later
|
1709
|
+
if(kbuf != l_build_buf){
|
1710
|
+
boost::move(xbuf.data()+kbuf-l_merged, xbuf.data() + kbuf, first_block-l_merged+elements_in_blocks);
|
1711
|
+
}
|
1712
|
+
}
|
1713
|
+
else{
|
1714
|
+
l_merged = insertion_sort_step(first_block, elements_in_blocks, l_base, comp);
|
1715
|
+
rotate_gcd(first_block - l_merged, first_block, first_block+elements_in_blocks);
|
1716
|
+
}
|
1717
|
+
|
1718
|
+
//Now combine elements using the buffer. Elements from buffer can't be
|
1719
|
+
//overwritten since xbuf was not big enough, so merge swapping elements.
|
1720
|
+
l_merged = op_merge_left_step_multiple
|
1721
|
+
(first_block - l_merged, elements_in_blocks, l_merged, l_build_buf, l_build_buf - l_merged, comp, swap_op());
|
1722
|
+
|
1723
|
+
BOOST_ASSERT(l_merged == l_build_buf);
|
1724
|
+
|
1725
|
+
//////////////////////////////////
|
1726
|
+
// Start of merge to right step
|
1727
|
+
//////////////////////////////////
|
1728
|
+
|
1729
|
+
//If kbuf is l_build_buf then we can merge right without swapping
|
1730
|
+
//Saved data is still in xbuf
|
1731
|
+
if(kbuf && kbuf == l_build_buf){
|
1732
|
+
op_merge_right_step_once(first, elements_in_blocks, l_build_buf, comp, move_op());
|
1733
|
+
//Restore internal buffer from external buffer if kbuf was l_build_buf.
|
1734
|
+
//as this operation was previously delayed.
|
1735
|
+
boost::move(xbuf.data(), xbuf.data() + kbuf, first);
|
1736
|
+
}
|
1737
|
+
else{
|
1738
|
+
op_merge_right_step_once(first, elements_in_blocks, l_build_buf, comp, swap_op());
|
1739
|
+
}
|
1740
|
+
xbuf.clear();
|
1741
|
+
//2*l_build_buf or total already merged
|
1742
|
+
return min_value(elements_in_blocks, 2*l_build_buf);
|
1743
|
+
}
|
1744
|
+
|
1745
|
+
template<class RandItKeys, class KeyCompare, class RandIt, class Compare, class XBuf>
|
1746
|
+
void adaptive_sort_combine_blocks
|
1747
|
+
( RandItKeys const keys
|
1748
|
+
, KeyCompare key_comp
|
1749
|
+
, RandIt const first
|
1750
|
+
, typename iterator_traits<RandIt>::size_type const len
|
1751
|
+
, typename iterator_traits<RandIt>::size_type const l_prev_merged
|
1752
|
+
, typename iterator_traits<RandIt>::size_type const l_block
|
1753
|
+
, bool const use_buf
|
1754
|
+
, bool const xbuf_used
|
1755
|
+
, XBuf & xbuf
|
1756
|
+
, Compare comp
|
1757
|
+
, bool merge_left)
|
1758
|
+
{
|
1759
|
+
(void)xbuf;
|
1760
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1761
|
+
|
1762
|
+
size_type const l_reg_combined = 2*l_prev_merged;
|
1763
|
+
size_type l_irreg_combined = 0;
|
1764
|
+
size_type const l_total_combined = calculate_total_combined(len, l_prev_merged, &l_irreg_combined);
|
1765
|
+
size_type const n_reg_combined = len/l_reg_combined;
|
1766
|
+
RandIt combined_first = first;
|
1767
|
+
|
1768
|
+
(void)l_total_combined;
|
1769
|
+
BOOST_ASSERT(l_total_combined <= len);
|
1770
|
+
|
1771
|
+
size_type const max_i = n_reg_combined + (l_irreg_combined != 0);
|
1772
|
+
|
1773
|
+
if(merge_left || !use_buf) {
|
1774
|
+
for( size_type combined_i = 0; combined_i != max_i; ++combined_i, combined_first += l_reg_combined) {
|
1775
|
+
//Now merge blocks
|
1776
|
+
bool const is_last = combined_i==n_reg_combined;
|
1777
|
+
size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
|
1778
|
+
|
1779
|
+
range_xbuf<RandIt, move_op> rbuf( (use_buf && xbuf_used) ? (combined_first-l_block) : combined_first, combined_first);
|
1780
|
+
size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
|
1781
|
+
combine_params( keys, key_comp, l_cur_combined
|
1782
|
+
, l_prev_merged, l_block, rbuf
|
1783
|
+
, n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
|
1784
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A combpar: ", len + l_block);
|
1785
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
|
1786
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp));
|
1787
|
+
if(!use_buf){
|
1788
|
+
merge_blocks_bufferless
|
1789
|
+
(keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp);
|
1790
|
+
}
|
1791
|
+
else{
|
1792
|
+
merge_blocks_left
|
1793
|
+
(keys, key_comp, combined_first, l_block, 0u, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
|
1794
|
+
}
|
1795
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After merge_blocks_l: ", len + l_block);
|
1796
|
+
}
|
1797
|
+
}
|
1798
|
+
else{
|
1799
|
+
combined_first += l_reg_combined*(max_i-1);
|
1800
|
+
for( size_type combined_i = max_i; combined_i--; combined_first -= l_reg_combined) {
|
1801
|
+
bool const is_last = combined_i==n_reg_combined;
|
1802
|
+
size_type const l_cur_combined = is_last ? l_irreg_combined : l_reg_combined;
|
1803
|
+
|
1804
|
+
RandIt const combined_last(combined_first+l_cur_combined);
|
1805
|
+
range_xbuf<RandIt, move_op> rbuf(combined_last, xbuf_used ? (combined_last+l_block) : combined_last);
|
1806
|
+
size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
|
1807
|
+
combine_params( keys, key_comp, l_cur_combined
|
1808
|
+
, l_prev_merged, l_block, rbuf
|
1809
|
+
, n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
|
1810
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A combpar: ", len + l_block);
|
1811
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first, combined_first + n_block_a*l_block+l_irreg1, comp));
|
1812
|
+
BOOST_MOVE_ADAPTIVE_SORT_INVARIANT(is_sorted(combined_first + n_block_a*l_block+l_irreg1, combined_first + n_block_a*l_block+l_irreg1+n_block_b*l_block+l_irreg2, comp));
|
1813
|
+
merge_blocks_right
|
1814
|
+
(keys, key_comp, combined_first, l_block, n_block_a, n_block_b, l_irreg2, comp, xbuf_used);
|
1815
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After merge_blocks_r: ", len + l_block);
|
1816
|
+
}
|
1817
|
+
}
|
1818
|
+
}
|
1819
|
+
|
1820
|
+
//Returns true if buffer is placed in
|
1821
|
+
//[buffer+len-l_intbuf, buffer+len). Otherwise, buffer is
|
1822
|
+
//[buffer,buffer+l_intbuf)
|
1823
|
+
template<class RandIt, class Compare>
|
1824
|
+
bool adaptive_sort_combine_all_blocks
|
1825
|
+
( RandIt keys
|
1826
|
+
, typename iterator_traits<RandIt>::size_type &n_keys
|
1827
|
+
, RandIt const buffer
|
1828
|
+
, typename iterator_traits<RandIt>::size_type const l_buf_plus_data
|
1829
|
+
, typename iterator_traits<RandIt>::size_type l_merged
|
1830
|
+
, typename iterator_traits<RandIt>::size_type &l_intbuf
|
1831
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
|
1832
|
+
, Compare comp)
|
1833
|
+
{
|
1834
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1835
|
+
RandIt const first = buffer + l_intbuf;
|
1836
|
+
size_type const l_data = l_buf_plus_data - l_intbuf;
|
1837
|
+
size_type const l_unique = l_intbuf+n_keys;
|
1838
|
+
//Backup data to external buffer once if possible
|
1839
|
+
bool const common_xbuf = l_data > l_merged && l_intbuf && l_intbuf <= xbuf.capacity();
|
1840
|
+
if(common_xbuf){
|
1841
|
+
xbuf.move_assign(buffer, l_intbuf);
|
1842
|
+
}
|
1843
|
+
|
1844
|
+
bool prev_merge_left = true;
|
1845
|
+
size_type l_prev_total_combined = l_merged, l_prev_block = 0;
|
1846
|
+
bool prev_use_internal_buf = true;
|
1847
|
+
|
1848
|
+
for( size_type n = 0; l_data > l_merged
|
1849
|
+
; l_merged*=2
|
1850
|
+
, ++n){
|
1851
|
+
//If l_intbuf is non-zero, use that internal buffer.
|
1852
|
+
// Implies l_block == l_intbuf && use_internal_buf == true
|
1853
|
+
//If l_intbuf is zero, see if half keys can be reused as a reduced emergency buffer,
|
1854
|
+
// Implies l_block == n_keys/2 && use_internal_buf == true
|
1855
|
+
//Otherwise, just give up and and use all keys to merge using rotations (use_internal_buf = false)
|
1856
|
+
bool use_internal_buf = false;
|
1857
|
+
size_type const l_block = lblock_for_combine(l_intbuf, n_keys, 2*l_merged, use_internal_buf);
|
1858
|
+
BOOST_ASSERT(!l_intbuf || (l_block == l_intbuf));
|
1859
|
+
BOOST_ASSERT(n == 0 || (!use_internal_buf || prev_use_internal_buf) );
|
1860
|
+
BOOST_ASSERT(n == 0 || (!use_internal_buf || l_prev_block == l_block) );
|
1861
|
+
|
1862
|
+
bool const is_merge_left = (n&1) == 0;
|
1863
|
+
size_type const l_total_combined = calculate_total_combined(l_data, l_merged);
|
1864
|
+
if(n && prev_use_internal_buf && prev_merge_left){
|
1865
|
+
if(is_merge_left || !use_internal_buf){
|
1866
|
+
move_data_backward(first-l_prev_block, l_prev_total_combined, first, common_xbuf);
|
1867
|
+
}
|
1868
|
+
else{
|
1869
|
+
//Put the buffer just after l_total_combined
|
1870
|
+
RandIt const buf_end = first+l_prev_total_combined;
|
1871
|
+
RandIt const buf_beg = buf_end-l_block;
|
1872
|
+
if(l_prev_total_combined > l_total_combined){
|
1873
|
+
size_type const l_diff = l_prev_total_combined - l_total_combined;
|
1874
|
+
move_data_backward(buf_beg-l_diff, l_diff, buf_end-l_diff, common_xbuf);
|
1875
|
+
}
|
1876
|
+
else if(l_prev_total_combined < l_total_combined){
|
1877
|
+
size_type const l_diff = l_total_combined - l_prev_total_combined;
|
1878
|
+
move_data_forward(buf_end, l_diff, buf_beg, common_xbuf);
|
1879
|
+
}
|
1880
|
+
}
|
1881
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After move_data : ", l_data + l_intbuf);
|
1882
|
+
}
|
1883
|
+
|
1884
|
+
//Combine to form l_merged*2 segments
|
1885
|
+
if(n_keys){
|
1886
|
+
adaptive_sort_combine_blocks
|
1887
|
+
( keys, comp, !use_internal_buf || is_merge_left ? first : first-l_block
|
1888
|
+
, l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
|
1889
|
+
}
|
1890
|
+
else{
|
1891
|
+
size_type *const uint_keys = xbuf.template aligned_trailing<size_type>();
|
1892
|
+
adaptive_sort_combine_blocks
|
1893
|
+
( uint_keys, less(), !use_internal_buf || is_merge_left ? first : first-l_block
|
1894
|
+
, l_data, l_merged, l_block, use_internal_buf, common_xbuf, xbuf, comp, is_merge_left);
|
1895
|
+
}
|
1896
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After combine_blocks: ", l_data + l_intbuf);
|
1897
|
+
prev_merge_left = is_merge_left;
|
1898
|
+
l_prev_total_combined = l_total_combined;
|
1899
|
+
l_prev_block = l_block;
|
1900
|
+
prev_use_internal_buf = use_internal_buf;
|
1901
|
+
}
|
1902
|
+
BOOST_ASSERT(l_prev_total_combined == l_data);
|
1903
|
+
bool const buffer_right = prev_use_internal_buf && prev_merge_left;
|
1904
|
+
|
1905
|
+
l_intbuf = prev_use_internal_buf ? l_prev_block : 0u;
|
1906
|
+
n_keys = l_unique - l_intbuf;
|
1907
|
+
//Restore data from to external common buffer if used
|
1908
|
+
if(common_xbuf){
|
1909
|
+
if(buffer_right){
|
1910
|
+
boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer+l_data);
|
1911
|
+
}
|
1912
|
+
else{
|
1913
|
+
boost::move(xbuf.data(), xbuf.data() + l_intbuf, buffer);
|
1914
|
+
}
|
1915
|
+
}
|
1916
|
+
return buffer_right;
|
1917
|
+
}
|
1918
|
+
|
1919
|
+
template<class RandIt, class Compare>
|
1920
|
+
void stable_merge
|
1921
|
+
( RandIt first, RandIt const middle, RandIt last
|
1922
|
+
, Compare comp
|
1923
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> &xbuf)
|
1924
|
+
{
|
1925
|
+
BOOST_ASSERT(xbuf.empty());
|
1926
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1927
|
+
size_type const len1 = size_type(middle-first);
|
1928
|
+
size_type const len2 = size_type(last-middle);
|
1929
|
+
size_type const l_min = min_value(len1, len2);
|
1930
|
+
if(xbuf.capacity() >= l_min){
|
1931
|
+
buffered_merge(first, middle, last, comp, xbuf);
|
1932
|
+
xbuf.clear();
|
1933
|
+
}
|
1934
|
+
else{
|
1935
|
+
merge_bufferless(first, middle, last, comp);
|
1936
|
+
}
|
1937
|
+
}
|
1938
|
+
|
1939
|
+
|
1940
|
+
template<class RandIt, class Compare>
|
1941
|
+
void adaptive_sort_final_merge( bool buffer_right
|
1942
|
+
, RandIt const first
|
1943
|
+
, typename iterator_traits<RandIt>::size_type const l_intbuf
|
1944
|
+
, typename iterator_traits<RandIt>::size_type const n_keys
|
1945
|
+
, typename iterator_traits<RandIt>::size_type const len
|
1946
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
|
1947
|
+
, Compare comp)
|
1948
|
+
{
|
1949
|
+
//BOOST_ASSERT(n_keys || xbuf.size() == l_intbuf);
|
1950
|
+
xbuf.clear();
|
1951
|
+
|
1952
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
1953
|
+
size_type const n_key_plus_buf = l_intbuf+n_keys;
|
1954
|
+
if(buffer_right){
|
1955
|
+
stable_sort(first+len-l_intbuf, first+len, comp, xbuf);
|
1956
|
+
stable_merge(first+n_keys, first+len-l_intbuf, first+len, antistable<Compare>(comp), xbuf);
|
1957
|
+
stable_sort(first, first+n_keys, comp, xbuf);
|
1958
|
+
stable_merge(first, first+n_keys, first+len, comp, xbuf);
|
1959
|
+
}
|
1960
|
+
else{
|
1961
|
+
stable_sort(first, first+n_key_plus_buf, comp, xbuf);
|
1962
|
+
if(xbuf.capacity() >= n_key_plus_buf){
|
1963
|
+
buffered_merge(first, first+n_key_plus_buf, first+len, comp, xbuf);
|
1964
|
+
}
|
1965
|
+
else if(xbuf.capacity() >= min_value<size_type>(l_intbuf, n_keys)){
|
1966
|
+
stable_merge(first+n_keys, first+n_key_plus_buf, first+len, comp, xbuf);
|
1967
|
+
stable_merge(first, first+n_keys, first+len, comp, xbuf);
|
1968
|
+
}
|
1969
|
+
else{
|
1970
|
+
merge_bufferless(first, first+n_key_plus_buf, first+len, comp);
|
1971
|
+
}
|
1972
|
+
}
|
1973
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After final_merge : ", len);
|
1974
|
+
}
|
1975
|
+
|
1976
|
+
template<class RandIt, class Compare, class Unsigned, class T>
|
1977
|
+
bool adaptive_sort_build_params
|
1978
|
+
(RandIt first, Unsigned const len, Compare comp
|
1979
|
+
, Unsigned &n_keys, Unsigned &l_intbuf, Unsigned &l_base, Unsigned &l_build_buf
|
1980
|
+
, adaptive_xbuf<T> & xbuf
|
1981
|
+
)
|
1982
|
+
{
|
1983
|
+
typedef Unsigned size_type;
|
1984
|
+
|
1985
|
+
//Calculate ideal parameters and try to collect needed unique keys
|
1986
|
+
l_base = 0u;
|
1987
|
+
|
1988
|
+
//Try to find a value near sqrt(len) that is 2^N*l_base where
|
1989
|
+
//l_base <= AdaptiveSortInsertionSortThreshold. This property is important
|
1990
|
+
//as build_blocks merges to the left iteratively duplicating the
|
1991
|
+
//merged size and all the buffer must be used just before the final
|
1992
|
+
//merge to right step. This guarantees "build_blocks" produces
|
1993
|
+
//segments of size l_build_buf*2, maximizing the classic merge phase.
|
1994
|
+
l_intbuf = size_type(ceil_sqrt_multiple(len, &l_base));
|
1995
|
+
|
1996
|
+
//The internal buffer can be expanded if there is enough external memory
|
1997
|
+
while(xbuf.capacity() >= l_intbuf*2){
|
1998
|
+
l_intbuf *= 2;
|
1999
|
+
}
|
2000
|
+
|
2001
|
+
//This is the minimum number of keys to implement the ideal algorithm
|
2002
|
+
//
|
2003
|
+
//l_intbuf is used as buffer plus the key count
|
2004
|
+
size_type n_min_ideal_keys = l_intbuf-1;
|
2005
|
+
while(n_min_ideal_keys >= (len-l_intbuf-n_min_ideal_keys)/l_intbuf){
|
2006
|
+
--n_min_ideal_keys;
|
2007
|
+
}
|
2008
|
+
n_min_ideal_keys += 1;
|
2009
|
+
BOOST_ASSERT(n_min_ideal_keys <= l_intbuf);
|
2010
|
+
|
2011
|
+
if(xbuf.template supports_aligned_trailing<size_type>(l_intbuf, (len-l_intbuf-1)/l_intbuf+1)){
|
2012
|
+
n_keys = 0u;
|
2013
|
+
l_build_buf = l_intbuf;
|
2014
|
+
}
|
2015
|
+
else{
|
2016
|
+
//Try to achieve a l_build_buf of length l_intbuf*2, so that we can merge with that
|
2017
|
+
//l_intbuf*2 buffer in "build_blocks" and use half of them as buffer and the other half
|
2018
|
+
//as keys in combine_all_blocks. In that case n_keys >= n_min_ideal_keys but by a small margin.
|
2019
|
+
//
|
2020
|
+
//If available memory is 2*sqrt(l), then only sqrt(l) unique keys are needed,
|
2021
|
+
//(to be used for keys in combine_all_blocks) as the whole l_build_buf
|
2022
|
+
//will be backuped in the buffer during build_blocks.
|
2023
|
+
bool const non_unique_buf = xbuf.capacity() >= l_intbuf;
|
2024
|
+
size_type const to_collect = non_unique_buf ? n_min_ideal_keys : l_intbuf*2;
|
2025
|
+
size_type collected = collect_unique(first, first+len, to_collect, comp, xbuf);
|
2026
|
+
|
2027
|
+
//If available memory is 2*sqrt(l), then for "build_params"
|
2028
|
+
//the situation is the same as if 2*l_intbuf were collected.
|
2029
|
+
if(non_unique_buf && collected == n_min_ideal_keys){
|
2030
|
+
l_build_buf = l_intbuf;
|
2031
|
+
n_keys = n_min_ideal_keys;
|
2032
|
+
}
|
2033
|
+
else if(collected == 2*l_intbuf){
|
2034
|
+
//l_intbuf*2 elements found. Use all of them in the build phase
|
2035
|
+
l_build_buf = l_intbuf*2;
|
2036
|
+
n_keys = l_intbuf;
|
2037
|
+
}
|
2038
|
+
else if(collected == (n_min_ideal_keys+l_intbuf)){
|
2039
|
+
l_build_buf = l_intbuf;
|
2040
|
+
n_keys = n_min_ideal_keys;
|
2041
|
+
}
|
2042
|
+
//If collected keys are not enough, try to fix n_keys and l_intbuf. If no fix
|
2043
|
+
//is possible (due to very low unique keys), then go to a slow sort based on rotations.
|
2044
|
+
else{
|
2045
|
+
BOOST_ASSERT(collected < (n_min_ideal_keys+l_intbuf));
|
2046
|
+
if(collected < 4){ //No combination possible with less that 4 keys
|
2047
|
+
return false;
|
2048
|
+
}
|
2049
|
+
n_keys = l_intbuf;
|
2050
|
+
while(n_keys&(n_keys-1)){
|
2051
|
+
n_keys &= n_keys-1; // make it power or 2
|
2052
|
+
}
|
2053
|
+
while(n_keys > collected){
|
2054
|
+
n_keys/=2;
|
2055
|
+
}
|
2056
|
+
//AdaptiveSortInsertionSortThreshold is always power of two so the minimum is power of two
|
2057
|
+
l_base = min_value<Unsigned>(n_keys, AdaptiveSortInsertionSortThreshold);
|
2058
|
+
l_intbuf = 0;
|
2059
|
+
l_build_buf = n_keys;
|
2060
|
+
}
|
2061
|
+
BOOST_ASSERT((n_keys+l_intbuf) >= l_build_buf);
|
2062
|
+
}
|
2063
|
+
|
2064
|
+
return true;
|
2065
|
+
}
|
2066
|
+
|
2067
|
+
template<class RandIt, class Compare>
|
2068
|
+
inline void adaptive_merge_combine_blocks( RandIt first
|
2069
|
+
, typename iterator_traits<RandIt>::size_type len1
|
2070
|
+
, typename iterator_traits<RandIt>::size_type len2
|
2071
|
+
, typename iterator_traits<RandIt>::size_type collected
|
2072
|
+
, typename iterator_traits<RandIt>::size_type n_keys
|
2073
|
+
, typename iterator_traits<RandIt>::size_type l_block
|
2074
|
+
, bool use_internal_buf
|
2075
|
+
, bool xbuf_used
|
2076
|
+
, Compare comp
|
2077
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
|
2078
|
+
)
|
2079
|
+
{
|
2080
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
2081
|
+
size_type const len = len1+len2;
|
2082
|
+
size_type const l_combine = len-collected;
|
2083
|
+
size_type const l_combine1 = len1-collected;
|
2084
|
+
|
2085
|
+
if(n_keys){
|
2086
|
+
RandIt const first_data = first+collected;
|
2087
|
+
RandIt const keys = first;
|
2088
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A combine: ", len);
|
2089
|
+
if(xbuf_used){
|
2090
|
+
if(xbuf.size() < l_block){
|
2091
|
+
xbuf.initialize_until(l_block, *first);
|
2092
|
+
}
|
2093
|
+
BOOST_ASSERT(xbuf.size() >= l_block);
|
2094
|
+
size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
|
2095
|
+
combine_params( keys, comp, l_combine
|
2096
|
+
, l_combine1, l_block, xbuf
|
2097
|
+
, n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
|
2098
|
+
merge_blocks_with_buf
|
2099
|
+
(keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, xbuf.data(), xbuf_used);
|
2100
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg xbf: ", len);
|
2101
|
+
}
|
2102
|
+
else{
|
2103
|
+
size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
|
2104
|
+
combine_params( keys, comp, l_combine
|
2105
|
+
, l_combine1, l_block, xbuf
|
2106
|
+
, n_block_a, n_block_b, l_irreg1, l_irreg2); //Outputs
|
2107
|
+
if(use_internal_buf){
|
2108
|
+
merge_blocks_with_buf
|
2109
|
+
(keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, first_data-l_block, xbuf_used);
|
2110
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg buf: ", len);
|
2111
|
+
}
|
2112
|
+
else{
|
2113
|
+
merge_blocks_bufferless
|
2114
|
+
(keys, comp, first_data, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp);
|
2115
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg nbf: ", len);
|
2116
|
+
}
|
2117
|
+
}
|
2118
|
+
}
|
2119
|
+
else{
|
2120
|
+
xbuf.shrink_to_fit(l_block);
|
2121
|
+
if(xbuf.size() < l_block){
|
2122
|
+
xbuf.initialize_until(l_block, *first);
|
2123
|
+
}
|
2124
|
+
size_type *const uint_keys = xbuf.template aligned_trailing<size_type>(l_block);
|
2125
|
+
size_type n_block_a, n_block_b, l_irreg1, l_irreg2;
|
2126
|
+
combine_params( uint_keys, less(), l_combine
|
2127
|
+
, l_combine1, l_block, xbuf
|
2128
|
+
, n_block_a, n_block_b, l_irreg1, l_irreg2, true); //Outputs
|
2129
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A combine: ", len);
|
2130
|
+
BOOST_ASSERT(xbuf.size() >= l_block);
|
2131
|
+
merge_blocks_with_buf
|
2132
|
+
(uint_keys, less(), first, l_block, l_irreg1, n_block_a, n_block_b, l_irreg2, comp, xbuf.data(), true);
|
2133
|
+
xbuf.clear();
|
2134
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A mrg buf: ", len);
|
2135
|
+
}
|
2136
|
+
}
|
2137
|
+
|
2138
|
+
template<class RandIt, class Compare>
|
2139
|
+
inline void adaptive_merge_final_merge( RandIt first
|
2140
|
+
, typename iterator_traits<RandIt>::size_type len1
|
2141
|
+
, typename iterator_traits<RandIt>::size_type len2
|
2142
|
+
, typename iterator_traits<RandIt>::size_type collected
|
2143
|
+
, typename iterator_traits<RandIt>::size_type l_intbuf
|
2144
|
+
, typename iterator_traits<RandIt>::size_type l_block
|
2145
|
+
, bool use_internal_buf
|
2146
|
+
, bool xbuf_used
|
2147
|
+
, Compare comp
|
2148
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
|
2149
|
+
)
|
2150
|
+
{
|
2151
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
2152
|
+
(void)l_block;
|
2153
|
+
size_type n_keys = collected-l_intbuf;
|
2154
|
+
size_type len = len1+len2;
|
2155
|
+
if(use_internal_buf){
|
2156
|
+
if(xbuf_used){
|
2157
|
+
xbuf.clear();
|
2158
|
+
//Nothing to do
|
2159
|
+
if(n_keys){
|
2160
|
+
stable_sort(first, first+n_keys, comp, xbuf);
|
2161
|
+
stable_merge(first, first+n_keys, first+len, comp, xbuf);
|
2162
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A key mrg: ", len);
|
2163
|
+
}
|
2164
|
+
}
|
2165
|
+
else{
|
2166
|
+
xbuf.clear();
|
2167
|
+
stable_sort(first, first+collected, comp, xbuf);
|
2168
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A k/b srt: ", len);
|
2169
|
+
stable_merge(first, first+collected, first+len, comp, xbuf);
|
2170
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A k/b mrg: ", len);
|
2171
|
+
}
|
2172
|
+
}
|
2173
|
+
else{
|
2174
|
+
xbuf.clear();
|
2175
|
+
stable_sort(first, first+collected, comp, xbuf);
|
2176
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A k/b srt: ", len);
|
2177
|
+
stable_merge(first, first+collected, first+len1+len2, comp, xbuf);
|
2178
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" A k/b mrg: ", len);
|
2179
|
+
}
|
2180
|
+
}
|
2181
|
+
|
2182
|
+
template<class SizeType, class Xbuf>
|
2183
|
+
inline SizeType adaptive_merge_n_keys_intbuf(SizeType &rl_block, SizeType len1, SizeType len2, Xbuf & xbuf, SizeType &l_intbuf_inout)
|
2184
|
+
{
|
2185
|
+
typedef SizeType size_type;
|
2186
|
+
size_type l_block = rl_block;
|
2187
|
+
size_type l_intbuf = xbuf.capacity() >= l_block ? 0u : l_block;
|
2188
|
+
|
2189
|
+
while(xbuf.capacity() >= l_block*2){
|
2190
|
+
l_block *= 2;
|
2191
|
+
}
|
2192
|
+
|
2193
|
+
//This is the minimum number of keys to implement the ideal algorithm
|
2194
|
+
size_type n_keys = len1/l_block+len2/l_block;
|
2195
|
+
while(n_keys >= ((len1-l_intbuf-n_keys)/l_block + len2/l_block)){
|
2196
|
+
--n_keys;
|
2197
|
+
}
|
2198
|
+
++n_keys;
|
2199
|
+
BOOST_ASSERT(n_keys >= ((len1-l_intbuf-n_keys)/l_block + len2/l_block));
|
2200
|
+
|
2201
|
+
if(xbuf.template supports_aligned_trailing<size_type>(l_block, n_keys)){
|
2202
|
+
n_keys = 0u;
|
2203
|
+
}
|
2204
|
+
l_intbuf_inout = l_intbuf;
|
2205
|
+
rl_block = l_block;
|
2206
|
+
return n_keys;
|
2207
|
+
}
|
2208
|
+
|
2209
|
+
///////////////////////////////////////////////////////////////////////////////////////////
|
2210
|
+
///////////////////////////////////////////////////////////////////////////////////////////
|
2211
|
+
///////////////////////////////////////////////////////////////////////////////////////////
|
2212
|
+
///////////////////////////////////////////////////////////////////////////////////////////
|
2213
|
+
///////////////////////////////////////////////////////////////////////////////////////////
|
2214
|
+
///////////////////////////////////////////////////////////////////////////////////////////
|
2215
|
+
///////////////////////////////////////////////////////////////////////////////////////////
|
2216
|
+
|
2217
|
+
// Main explanation of the sort algorithm.
|
2218
|
+
//
|
2219
|
+
// csqrtlen = ceil(sqrt(len));
|
2220
|
+
//
|
2221
|
+
// * First, 2*csqrtlen unique elements elements are extracted from elements to be
|
2222
|
+
// sorted and placed in the beginning of the range.
|
2223
|
+
//
|
2224
|
+
// * Step "build_blocks": In this nearly-classic merge step, 2*csqrtlen unique elements
|
2225
|
+
// will be used as auxiliary memory, so trailing len-2*csqrtlen elements are
|
2226
|
+
// are grouped in blocks of sorted 4*csqrtlen elements. At the end of the step
|
2227
|
+
// 2*csqrtlen unique elements are again the leading elements of the whole range.
|
2228
|
+
//
|
2229
|
+
// * Step "combine_blocks": pairs of previously formed blocks are merged with a different
|
2230
|
+
// ("smart") algorithm to form blocks of 8*csqrtlen elements. This step is slower than the
|
2231
|
+
// "build_blocks" step and repeated iteratively (forming blocks of 16*csqrtlen, 32*csqrtlen
|
2232
|
+
// elements, etc) of until all trailing (len-2*csqrtlen) elements are merged.
|
2233
|
+
//
|
2234
|
+
// In "combine_blocks" len/csqrtlen elements used are as "keys" (markers) to
|
2235
|
+
// know if elements belong to the first or second block to be merged and another
|
2236
|
+
// leading csqrtlen elements are used as buffer. Explanation of the "combine_blocks" step:
|
2237
|
+
//
|
2238
|
+
// Iteratively until all trailing (len-2*csqrtlen) elements are merged:
|
2239
|
+
// Iteratively for each pair of previously merged block:
|
2240
|
+
// * Blocks are divided groups of csqrtlen elements and
|
2241
|
+
// 2*merged_block/csqrtlen keys are sorted to be used as markers
|
2242
|
+
// * Groups are selection-sorted by first or last element (depending wheter they
|
2243
|
+
// merged to left or right) and keys are reordered accordingly as an imitation-buffer.
|
2244
|
+
// * Elements of each block pair are merged using the csqrtlen buffer taking into account
|
2245
|
+
// if they belong to the first half or second half (marked by the key).
|
2246
|
+
//
|
2247
|
+
// * In the final merge step leading elements (2*csqrtlen) are sorted and merged with
|
2248
|
+
// rotations with the rest of sorted elements in the "combine_blocks" step.
|
2249
|
+
//
|
2250
|
+
// Corner cases:
|
2251
|
+
//
|
2252
|
+
// * If no 2*csqrtlen elements can be extracted:
|
2253
|
+
//
|
2254
|
+
// * If csqrtlen+len/csqrtlen are extracted, then only csqrtlen elements are used
|
2255
|
+
// as buffer in the "build_blocks" step forming blocks of 2*csqrtlen elements. This
|
2256
|
+
// means that an additional "combine_blocks" step will be needed to merge all elements.
|
2257
|
+
//
|
2258
|
+
// * If no csqrtlen+len/csqrtlen elements can be extracted, but still more than a minimum,
|
2259
|
+
// then reduces the number of elements used as buffer and keys in the "build_blocks"
|
2260
|
+
// and "combine_blocks" steps. If "combine_blocks" has no enough keys due to this reduction
|
2261
|
+
// then uses a rotation based smart merge.
|
2262
|
+
//
|
2263
|
+
// * If the minimum number of keys can't be extracted, a rotation-based sorting is performed.
|
2264
|
+
//
|
2265
|
+
// * If auxiliary memory is more or equal than ceil(len/2), half-copying mergesort is used.
|
2266
|
+
//
|
2267
|
+
// * If auxiliary memory is more than csqrtlen+n_keys*sizeof(std::size_t),
|
2268
|
+
// then only csqrtlen elements need to be extracted and "combine_blocks" will use integral
|
2269
|
+
// keys to combine blocks.
|
2270
|
+
//
|
2271
|
+
// * If auxiliary memory is available, the "build_blocks" will be extended to build bigger blocks
|
2272
|
+
// using classic merge.
|
2273
|
+
template<class RandIt, class Compare>
|
2274
|
+
void adaptive_sort_impl
|
2275
|
+
( RandIt first
|
2276
|
+
, typename iterator_traits<RandIt>::size_type const len
|
2277
|
+
, Compare comp
|
2278
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
|
2279
|
+
)
|
2280
|
+
{
|
2281
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
2282
|
+
|
2283
|
+
//Small sorts go directly to insertion sort
|
2284
|
+
if(len <= size_type(AdaptiveSortInsertionSortThreshold)){
|
2285
|
+
insertion_sort(first, first + len, comp);
|
2286
|
+
return;
|
2287
|
+
}
|
2288
|
+
|
2289
|
+
if((len-len/2) <= xbuf.capacity()){
|
2290
|
+
merge_sort(first, first+len, comp, xbuf.data());
|
2291
|
+
return;
|
2292
|
+
}
|
2293
|
+
|
2294
|
+
//Make sure it is at least four
|
2295
|
+
BOOST_STATIC_ASSERT(AdaptiveSortInsertionSortThreshold >= 4);
|
2296
|
+
|
2297
|
+
size_type l_base = 0;
|
2298
|
+
size_type l_intbuf = 0;
|
2299
|
+
size_type n_keys = 0;
|
2300
|
+
size_type l_build_buf = 0;
|
2301
|
+
|
2302
|
+
//Calculate and extract needed unique elements. If a minimum is not achieved
|
2303
|
+
//fallback to rotation-based merge
|
2304
|
+
if(!adaptive_sort_build_params(first, len, comp, n_keys, l_intbuf, l_base, l_build_buf, xbuf)){
|
2305
|
+
stable_sort(first, first+len, comp, xbuf);
|
2306
|
+
return;
|
2307
|
+
}
|
2308
|
+
BOOST_ASSERT(l_build_buf);
|
2309
|
+
//Otherwise, continue the adaptive_sort
|
2310
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT("\n After collect_unique: ", len);
|
2311
|
+
size_type const n_key_plus_buf = l_intbuf+n_keys;
|
2312
|
+
//l_build_buf is always power of two if l_intbuf is zero
|
2313
|
+
BOOST_ASSERT(l_intbuf || (0 == (l_build_buf & (l_build_buf-1))));
|
2314
|
+
|
2315
|
+
//Classic merge sort until internal buffer and xbuf are exhausted
|
2316
|
+
size_type const l_merged = adaptive_sort_build_blocks
|
2317
|
+
(first+n_key_plus_buf-l_build_buf, len-n_key_plus_buf+l_build_buf, l_base, l_build_buf, xbuf, comp);
|
2318
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT(" After build_blocks: ", len);
|
2319
|
+
|
2320
|
+
//Non-trivial merge
|
2321
|
+
bool const buffer_right = adaptive_sort_combine_all_blocks
|
2322
|
+
(first, n_keys, first+n_keys, len-n_keys, l_merged, l_intbuf, xbuf, comp);
|
2323
|
+
|
2324
|
+
//Sort keys and buffer and merge the whole sequence
|
2325
|
+
adaptive_sort_final_merge(buffer_right, first, l_intbuf, n_keys, len, xbuf, comp);
|
2326
|
+
}
|
2327
|
+
|
2328
|
+
// Main explanation of the merge algorithm.
|
2329
|
+
//
|
2330
|
+
// csqrtlen = ceil(sqrt(len));
|
2331
|
+
//
|
2332
|
+
// * First, csqrtlen [to be used as buffer] + (len/csqrtlen - 1) [to be used as keys] => to_collect
|
2333
|
+
// unique elements are extracted from elements to be sorted and placed in the beginning of the range.
|
2334
|
+
//
|
2335
|
+
// * Step "combine_blocks": the leading (len1-to_collect) elements plus trailing len2 elements
|
2336
|
+
// are merged with a non-trivial ("smart") algorithm to form an ordered range trailing "len-to_collect" elements.
|
2337
|
+
//
|
2338
|
+
// Explanation of the "combine_blocks" step:
|
2339
|
+
//
|
2340
|
+
// * Trailing [first+to_collect, first+len1) elements are divided in groups of cqrtlen elements.
|
2341
|
+
// Remaining elements that can't form a group are grouped in front of those elements.
|
2342
|
+
// * Trailing [first+len1, first+len1+len2) elements are divided in groups of cqrtlen elements.
|
2343
|
+
// Remaining elements that can't form a group are grouped in the back of those elements.
|
2344
|
+
// * In parallel the following two steps are performed:
|
2345
|
+
// * Groups are selection-sorted by first or last element (depending wheter they
|
2346
|
+
// merged to left or right) and keys are reordered accordingly as an imitation-buffer.
|
2347
|
+
// * Elements of each block pair are merged using the csqrtlen buffer taking into account
|
2348
|
+
// if they belong to the first half or second half (marked by the key).
|
2349
|
+
//
|
2350
|
+
// * In the final merge step leading "to_collect" elements are merged with rotations
|
2351
|
+
// with the rest of merged elements in the "combine_blocks" step.
|
2352
|
+
//
|
2353
|
+
// Corner cases:
|
2354
|
+
//
|
2355
|
+
// * If no "to_collect" elements can be extracted:
|
2356
|
+
//
|
2357
|
+
// * If more than a minimum number of elements is extracted
|
2358
|
+
// then reduces the number of elements used as buffer and keys in the
|
2359
|
+
// and "combine_blocks" steps. If "combine_blocks" has no enough keys due to this reduction
|
2360
|
+
// then uses a rotation based smart merge.
|
2361
|
+
//
|
2362
|
+
// * If the minimum number of keys can't be extracted, a rotation-based merge is performed.
|
2363
|
+
//
|
2364
|
+
// * If auxiliary memory is more or equal than min(len1, len2), a buffered merge is performed.
|
2365
|
+
//
|
2366
|
+
// * If the len1 or len2 are less than 2*csqrtlen then a rotation-based merge is performed.
|
2367
|
+
//
|
2368
|
+
// * If auxiliary memory is more than csqrtlen+n_keys*sizeof(std::size_t),
|
2369
|
+
// then no csqrtlen need to be extracted and "combine_blocks" will use integral
|
2370
|
+
// keys to combine blocks.
|
2371
|
+
template<class RandIt, class Compare>
|
2372
|
+
void adaptive_merge_impl
|
2373
|
+
( RandIt first
|
2374
|
+
, typename iterator_traits<RandIt>::size_type const len1
|
2375
|
+
, typename iterator_traits<RandIt>::size_type const len2
|
2376
|
+
, Compare comp
|
2377
|
+
, adaptive_xbuf<typename iterator_traits<RandIt>::value_type> & xbuf
|
2378
|
+
)
|
2379
|
+
{
|
2380
|
+
typedef typename iterator_traits<RandIt>::size_type size_type;
|
2381
|
+
|
2382
|
+
if(xbuf.capacity() >= min_value<size_type>(len1, len2)){
|
2383
|
+
buffered_merge(first, first+len1, first+(len1+len2), comp, xbuf);
|
2384
|
+
}
|
2385
|
+
else{
|
2386
|
+
const size_type len = len1+len2;
|
2387
|
+
//Calculate ideal parameters and try to collect needed unique keys
|
2388
|
+
size_type l_block = size_type(ceil_sqrt(len));
|
2389
|
+
|
2390
|
+
//One range is not big enough to extract keys and the internal buffer so a
|
2391
|
+
//rotation-based based merge will do just fine
|
2392
|
+
if(len1 <= l_block*2 || len2 <= l_block*2){
|
2393
|
+
merge_bufferless(first, first+len1, first+len1+len2, comp);
|
2394
|
+
return;
|
2395
|
+
}
|
2396
|
+
|
2397
|
+
//Detail the number of keys and internal buffer. If xbuf has enough memory, no
|
2398
|
+
//internal buffer is needed so l_intbuf will remain 0.
|
2399
|
+
size_type l_intbuf = 0;
|
2400
|
+
size_type n_keys = adaptive_merge_n_keys_intbuf(l_block, len1, len2, xbuf, l_intbuf);
|
2401
|
+
size_type const to_collect = l_intbuf+n_keys;
|
2402
|
+
//Try to extract needed unique values from the first range
|
2403
|
+
size_type const collected = collect_unique(first, first+len1, to_collect, comp, xbuf);
|
2404
|
+
BOOST_MOVE_ADAPTIVE_SORT_PRINT("\n A collect: ", len);
|
2405
|
+
|
2406
|
+
//Not the minimum number of keys is not available on the first range, so fallback to rotations
|
2407
|
+
if(collected != to_collect && collected < 4){
|
2408
|
+
merge_bufferless(first, first+len1, first+len1+len2, comp);
|
2409
|
+
return;
|
2410
|
+
}
|
2411
|
+
|
2412
|
+
//If not enough keys but more than minimum, adjust the internal buffer and key count
|
2413
|
+
bool use_internal_buf = collected == to_collect;
|
2414
|
+
if (!use_internal_buf){
|
2415
|
+
l_intbuf = 0u;
|
2416
|
+
n_keys = collected;
|
2417
|
+
l_block = lblock_for_combine(l_intbuf, n_keys, len, use_internal_buf);
|
2418
|
+
//If use_internal_buf is false, then then internal buffer will be zero and rotation-based combination will be used
|
2419
|
+
l_intbuf = use_internal_buf ? l_block : 0u;
|
2420
|
+
}
|
2421
|
+
|
2422
|
+
bool const xbuf_used = collected == to_collect && xbuf.capacity() >= l_block;
|
2423
|
+
//Merge trailing elements using smart merges
|
2424
|
+
adaptive_merge_combine_blocks(first, len1, len2, collected, n_keys, l_block, use_internal_buf, xbuf_used, comp, xbuf);
|
2425
|
+
//Merge buffer and keys with the rest of the values
|
2426
|
+
adaptive_merge_final_merge (first, len1, len2, collected, l_intbuf, l_block, use_internal_buf, xbuf_used, comp, xbuf);
|
2427
|
+
}
|
2428
|
+
}
|
2429
|
+
|
2430
|
+
|
2431
|
+
} //namespace detail_adaptive {
|
2432
|
+
} //namespace movelib {
|
2433
|
+
} //namespace boost {
|
2434
|
+
|
2435
|
+
#include <boost/move/detail/config_end.hpp>
|
2436
|
+
|
2437
|
+
#endif //#define BOOST_MOVE_ADAPTIVE_SORT_MERGE_HPP
|