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.

Files changed (542) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +9 -0
  3. data/CHANGELOG +9 -0
  4. data/build/cxx_tests.rb +11 -1
  5. data/build/documentation.rb +0 -32
  6. data/build/support/cxx_dependency_map.rb +602 -2
  7. data/build/test_basics.rb +3 -3
  8. data/dev/boost-patches/0001-Patch-boost-thread-so-that-oxt-thread-can-use-it.patch +48 -0
  9. data/dev/boost-patches/0002-Make-boost-thread_interrupted-derive-from-oxt-tracab.patch +33 -0
  10. data/dev/boost-patches/0003-Disable-a-Clang-pragma-to-prevent-warnings-on-OS-X.patch +25 -0
  11. data/dev/ci/README.md +121 -0
  12. data/dev/ci/lib/functions.sh +129 -0
  13. data/dev/ci/lib/set-container-envvars.sh +46 -0
  14. data/dev/ci/lib/setup-container.sh +43 -0
  15. data/dev/ci/run-tests-natively +24 -0
  16. data/dev/ci/run-tests-with-docker +42 -0
  17. data/dev/ci/scripts/debug-console-wrapper.sh +27 -0
  18. data/dev/ci/scripts/docker-entrypoint-stage2.sh +17 -0
  19. data/dev/ci/scripts/docker-entrypoint.sh +17 -0
  20. data/dev/ci/scripts/inituidgid +17 -0
  21. data/dev/ci/scripts/run-tests-natively-stage2.sh +17 -0
  22. data/dev/ci/scripts/setup-host-natively.sh +11 -0
  23. data/dev/ci/setup-host +50 -0
  24. data/dev/ci/tests/apache2/run +6 -0
  25. data/dev/ci/tests/apache2/setup +4 -0
  26. data/dev/ci/tests/cxx/run +9 -0
  27. data/dev/ci/tests/cxx/setup +4 -0
  28. data/dev/ci/tests/nginx-dynamic/run +20 -0
  29. data/dev/ci/tests/nginx-dynamic/setup +4 -0
  30. data/dev/ci/tests/nginx/run +5 -0
  31. data/dev/ci/tests/nginx/setup +4 -0
  32. data/dev/ci/tests/nodejs/run +4 -0
  33. data/dev/ci/tests/nodejs/setup +4 -0
  34. data/dev/ci/tests/ruby/run +4 -0
  35. data/dev/ci/tests/ruby/setup +4 -0
  36. data/dev/ci/tests/source-packaging/run +4 -0
  37. data/dev/ci/tests/source-packaging/setup +4 -0
  38. data/dev/ci/tests/standalone/run +4 -0
  39. data/dev/ci/tests/standalone/setup +4 -0
  40. data/dev/copy_boost_headers +8 -2
  41. data/src/agent/Core/ApiServer.h +11 -5
  42. data/src/agent/Core/Controller.h +12 -46
  43. data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
  44. data/src/agent/Core/Controller/Config.h +369 -0
  45. data/src/agent/Core/Controller/ForwardResponse.cpp +4 -4
  46. data/src/agent/Core/Controller/Hooks.cpp +15 -3
  47. data/src/agent/Core/Controller/Implementation.cpp +1 -1
  48. data/src/agent/Core/Controller/InitRequest.cpp +28 -39
  49. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +25 -60
  50. data/src/agent/Core/Controller/InternalUtils.cpp +0 -16
  51. data/src/agent/Core/Controller/Miscellaneous.cpp +0 -17
  52. data/src/agent/Core/Controller/Request.h +2 -0
  53. data/src/agent/Core/Controller/SendRequest.cpp +4 -4
  54. data/src/agent/Core/Controller/{StateInspectionAndConfiguration.cpp → StateInspection.cpp} +0 -22
  55. data/src/agent/Core/Controller/TurboCaching.h +11 -10
  56. data/src/agent/Core/CoreMain.cpp +16 -6
  57. data/src/agent/Core/ResponseCache.h +3 -3
  58. data/src/agent/Core/SpawningKit/SmartSpawner.h +9 -3
  59. data/src/agent/Core/SpawningKit/Spawner.h +7 -3
  60. data/src/agent/UstRouter/ApiServer.h +3 -2
  61. data/src/agent/UstRouter/Controller.h +66 -32
  62. data/src/agent/UstRouter/UstRouterMain.cpp +10 -2
  63. data/src/agent/Watchdog/ApiServer.h +3 -2
  64. data/src/agent/Watchdog/WatchdogMain.cpp +3 -1
  65. data/src/apache2_module/ConfigurationCommands.cpp +1 -1
  66. data/src/cxx_supportlib/ConfigKit/Common.h +125 -0
  67. data/src/cxx_supportlib/ConfigKit/ConfigKit.h +34 -0
  68. data/src/cxx_supportlib/ConfigKit/README.md +895 -0
  69. data/src/cxx_supportlib/ConfigKit/Schema.h +331 -0
  70. data/src/cxx_supportlib/ConfigKit/Store.h +385 -0
  71. data/src/cxx_supportlib/ConfigKit/TableTranslator.h +185 -0
  72. data/src/cxx_supportlib/ConfigKit/Utils.h +141 -0
  73. data/src/cxx_supportlib/ConfigKit/VariantMapUtils.h +81 -0
  74. data/src/cxx_supportlib/Constants.h +1 -1
  75. data/src/cxx_supportlib/Crypto.cpp +2 -2
  76. data/src/cxx_supportlib/Logging.h +0 -35
  77. data/src/cxx_supportlib/ServerKit/HttpServer.h +35 -16
  78. data/src/cxx_supportlib/ServerKit/Server.h +65 -25
  79. data/src/cxx_supportlib/oxt/macros.hpp +3 -0
  80. data/src/cxx_supportlib/vendor-modified/boost/algorithm/string/replace.hpp +0 -2
  81. data/src/cxx_supportlib/vendor-modified/boost/array.hpp +53 -42
  82. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/atomic_template.hpp +11 -5
  83. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/bitwise_cast.hpp +13 -2
  84. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/caps_gcc_x86.hpp +23 -0
  85. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/caps_msvc_x86.hpp +5 -0
  86. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/config.hpp +3 -2
  87. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/interlocked.hpp +8 -1
  88. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_emulated.hpp +3 -1
  89. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_alpha.hpp +2 -0
  90. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_arm.hpp +2 -0
  91. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_atomic.hpp +5 -0
  92. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_ppc.hpp +2 -0
  93. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_sparc.hpp +6 -4
  94. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_sync.hpp +2 -0
  95. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_x86.hpp +3 -1
  96. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_x86_dcas.hpp +28 -17
  97. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_linux_arm.hpp +2 -0
  98. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_msvc_arm.hpp +2 -0
  99. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_msvc_x86.hpp +9 -4
  100. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/platform.hpp +3 -3
  101. data/src/cxx_supportlib/vendor-modified/boost/bind/arg.hpp +10 -3
  102. data/src/cxx_supportlib/vendor-modified/boost/bind/bind.hpp +90 -18
  103. data/src/cxx_supportlib/vendor-modified/boost/cerrno.hpp +2 -2
  104. data/src/cxx_supportlib/vendor-modified/boost/chrono/duration.hpp +1 -1
  105. data/src/cxx_supportlib/vendor-modified/boost/config/auto_link.hpp +8 -3
  106. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/borland.hpp +2 -0
  107. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/clang.hpp +35 -6
  108. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/codegear.hpp +2 -0
  109. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/comeau.hpp +1 -1
  110. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/common_edg.hpp +2 -0
  111. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/compaq_cxx.hpp +1 -1
  112. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/cray.hpp +3 -1
  113. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/digitalmars.hpp +2 -0
  114. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/gcc.hpp +19 -4
  115. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/gcc_xml.hpp +3 -1
  116. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/greenhills.hpp +1 -1
  117. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/hp_acc.hpp +3 -1
  118. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/intel.hpp +29 -7
  119. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/kai.hpp +1 -1
  120. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/metrowerks.hpp +2 -0
  121. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/mpw.hpp +2 -0
  122. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/nvcc.hpp +16 -0
  123. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/pathscale.hpp +2 -0
  124. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/pgi.hpp +2 -0
  125. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/sgi_mipspro.hpp +1 -1
  126. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/sunpro_cc.hpp +10 -1
  127. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/vacpp.hpp +2 -0
  128. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/visualc.hpp +44 -16
  129. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/xlcpp.hpp +4 -0
  130. data/src/cxx_supportlib/vendor-modified/boost/config/platform/cygwin.hpp +1 -2
  131. data/src/cxx_supportlib/vendor-modified/boost/config/platform/linux.hpp +1 -1
  132. data/src/cxx_supportlib/vendor-modified/boost/config/select_compiler_config.hpp +21 -21
  133. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/dinkumware.hpp +42 -1
  134. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libcomo.hpp +7 -0
  135. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libcpp.hpp +40 -7
  136. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libstdcpp3.hpp +39 -6
  137. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/modena.hpp +7 -0
  138. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/msl.hpp +7 -0
  139. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/roguewave.hpp +7 -0
  140. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/sgi.hpp +8 -1
  141. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/stlport.hpp +7 -0
  142. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/vacpp.hpp +7 -0
  143. data/src/cxx_supportlib/vendor-modified/boost/config/suffix.hpp +33 -4
  144. data/src/cxx_supportlib/vendor-modified/boost/container/adaptive_pool.hpp +0 -2
  145. data/src/cxx_supportlib/vendor-modified/boost/container/allocator.hpp +0 -3
  146. data/src/cxx_supportlib/vendor-modified/boost/container/allocator_traits.hpp +34 -27
  147. data/src/cxx_supportlib/vendor-modified/boost/container/deque.hpp +62 -26
  148. data/src/cxx_supportlib/vendor-modified/boost/container/detail/addressof.hpp +2 -2
  149. data/src/cxx_supportlib/vendor-modified/boost/container/detail/advanced_insert_int.hpp +4 -4
  150. data/src/cxx_supportlib/vendor-modified/boost/container/detail/compare_functors.hpp +4 -4
  151. data/src/cxx_supportlib/vendor-modified/boost/container/detail/config_begin.hpp +2 -0
  152. data/src/cxx_supportlib/vendor-modified/boost/container/detail/construct_in_place.hpp +39 -5
  153. data/src/cxx_supportlib/vendor-modified/boost/container/detail/copy_move_algo.hpp +49 -32
  154. data/src/cxx_supportlib/vendor-modified/boost/container/detail/dispatch_uses_allocator.hpp +175 -7
  155. data/src/cxx_supportlib/vendor-modified/boost/container/detail/flat_tree.hpp +223 -98
  156. data/src/cxx_supportlib/vendor-modified/boost/container/detail/is_sorted.hpp +57 -0
  157. data/src/cxx_supportlib/vendor-modified/boost/container/detail/iterators.hpp +88 -41
  158. data/src/cxx_supportlib/vendor-modified/boost/container/detail/mpl.hpp +7 -8
  159. data/src/cxx_supportlib/vendor-modified/boost/container/detail/mutex.hpp +4 -9
  160. data/src/cxx_supportlib/vendor-modified/boost/container/detail/node_alloc_holder.hpp +45 -18
  161. data/src/cxx_supportlib/vendor-modified/boost/container/detail/pair.hpp +205 -26
  162. data/src/cxx_supportlib/vendor-modified/boost/container/detail/tree.hpp +290 -181
  163. data/src/cxx_supportlib/vendor-modified/boost/container/detail/value_init.hpp +2 -0
  164. data/src/cxx_supportlib/vendor-modified/boost/container/detail/variadic_templates_tools.hpp +24 -19
  165. data/src/cxx_supportlib/vendor-modified/boost/container/detail/workaround.hpp +38 -0
  166. data/src/cxx_supportlib/vendor-modified/boost/container/flat_map.hpp +320 -46
  167. data/src/cxx_supportlib/vendor-modified/boost/container/flat_set.hpp +91 -18
  168. data/src/cxx_supportlib/vendor-modified/boost/container/list.hpp +23 -19
  169. data/src/cxx_supportlib/vendor-modified/boost/container/map.hpp +491 -120
  170. data/src/cxx_supportlib/vendor-modified/boost/container/new_allocator.hpp +4 -4
  171. data/src/cxx_supportlib/vendor-modified/boost/container/node_allocator.hpp +0 -3
  172. data/src/cxx_supportlib/vendor-modified/boost/container/node_handle.hpp +399 -0
  173. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/deque.hpp +2 -0
  174. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/flat_map.hpp +4 -0
  175. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/flat_set.hpp +4 -0
  176. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/list.hpp +2 -0
  177. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/map.hpp +4 -0
  178. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/set.hpp +4 -0
  179. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/slist.hpp +2 -0
  180. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/small_vector.hpp +2 -0
  181. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/stable_vector.hpp +2 -0
  182. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/string.hpp +2 -0
  183. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/vector.hpp +2 -0
  184. data/src/cxx_supportlib/vendor-modified/boost/container/set.hpp +101 -20
  185. data/src/cxx_supportlib/vendor-modified/boost/container/slist.hpp +19 -14
  186. data/src/cxx_supportlib/vendor-modified/boost/container/small_vector.hpp +117 -59
  187. data/src/cxx_supportlib/vendor-modified/boost/container/stable_vector.hpp +8 -6
  188. data/src/cxx_supportlib/vendor-modified/boost/container/static_vector.hpp +33 -28
  189. data/src/cxx_supportlib/vendor-modified/boost/container/string.hpp +414 -70
  190. data/src/cxx_supportlib/vendor-modified/boost/container/throw_exception.hpp +1 -0
  191. data/src/cxx_supportlib/vendor-modified/boost/container/uses_allocator_fwd.hpp +2 -2
  192. data/src/cxx_supportlib/vendor-modified/boost/container/vector.hpp +134 -117
  193. data/src/cxx_supportlib/vendor-modified/boost/core/addressof.hpp +202 -99
  194. data/src/cxx_supportlib/vendor-modified/boost/core/demangle.hpp +8 -10
  195. data/src/cxx_supportlib/vendor-modified/boost/core/lightweight_test.hpp +217 -1
  196. data/src/cxx_supportlib/vendor-modified/boost/core/scoped_enum.hpp +29 -27
  197. data/src/cxx_supportlib/vendor-modified/boost/current_function.hpp +5 -1
  198. data/src/cxx_supportlib/vendor-modified/boost/date_time/c_time.hpp +13 -13
  199. data/src/cxx_supportlib/vendor-modified/boost/date_time/constrained_value.hpp +3 -3
  200. data/src/cxx_supportlib/vendor-modified/boost/date_time/date.hpp +2 -1
  201. data/src/cxx_supportlib/vendor-modified/boost/date_time/date_duration.hpp +4 -3
  202. data/src/cxx_supportlib/vendor-modified/boost/date_time/date_duration_types.hpp +6 -5
  203. data/src/cxx_supportlib/vendor-modified/boost/date_time/date_facet.hpp +2 -2
  204. data/src/cxx_supportlib/vendor-modified/boost/date_time/date_names_put.hpp +8 -7
  205. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_calendar.hpp +2 -1
  206. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_date.hpp +2 -1
  207. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_day.hpp +4 -3
  208. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_day_of_year.hpp +3 -2
  209. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_duration.hpp +2 -1
  210. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_duration_types.hpp +4 -3
  211. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_facet.hpp +27 -7
  212. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_month.hpp +5 -5
  213. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_serialize.hpp +5 -0
  214. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_weekday.hpp +4 -4
  215. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian/greg_year.hpp +4 -5
  216. data/src/cxx_supportlib/vendor-modified/boost/date_time/gregorian_calendar.hpp +2 -1
  217. data/src/cxx_supportlib/vendor-modified/boost/date_time/local_time/local_date_time.hpp +5 -4
  218. data/src/cxx_supportlib/vendor-modified/boost/date_time/local_time/posix_time_zone.hpp +4 -3
  219. data/src/cxx_supportlib/vendor-modified/boost/date_time/period.hpp +3 -2
  220. data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/date_duration_operators.hpp +1 -1
  221. data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/posix_time_config.hpp +2 -2
  222. data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/posix_time_duration.hpp +5 -4
  223. data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/ptime.hpp +6 -5
  224. data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/time_parsers.hpp +4 -0
  225. data/src/cxx_supportlib/vendor-modified/boost/date_time/time_duration.hpp +2 -2
  226. data/src/cxx_supportlib/vendor-modified/boost/date_time/time_facet.hpp +5 -4
  227. data/src/cxx_supportlib/vendor-modified/boost/date_time/time_zone_base.hpp +2 -1
  228. data/src/cxx_supportlib/vendor-modified/boost/date_time/year_month_day.hpp +3 -1
  229. data/src/cxx_supportlib/vendor-modified/boost/detail/iterator.hpp +13 -0
  230. data/src/cxx_supportlib/vendor-modified/boost/detail/lcast_precision.hpp +1 -0
  231. data/src/cxx_supportlib/vendor-modified/boost/detail/workaround.hpp +5 -0
  232. data/src/cxx_supportlib/vendor-modified/boost/exception/detail/error_info_impl.hpp +11 -0
  233. data/src/cxx_supportlib/vendor-modified/boost/exception/detail/shared_ptr.hpp +17 -0
  234. data/src/cxx_supportlib/vendor-modified/boost/exception/exception.hpp +25 -3
  235. data/src/cxx_supportlib/vendor-modified/boost/exception/get_error_info.hpp +2 -1
  236. data/src/cxx_supportlib/vendor-modified/boost/exception/info.hpp +114 -1
  237. data/src/cxx_supportlib/vendor-modified/boost/function/function_base.hpp +116 -142
  238. data/src/cxx_supportlib/vendor-modified/boost/function/function_template.hpp +57 -69
  239. data/src/cxx_supportlib/vendor-modified/boost/functional/hash/detail/hash_float.hpp +1 -1
  240. data/src/cxx_supportlib/vendor-modified/boost/functional/hash/extensions.hpp +3 -3
  241. data/src/cxx_supportlib/vendor-modified/boost/functional/hash/hash.hpp +27 -13
  242. data/src/cxx_supportlib/vendor-modified/boost/intrusive/any_hook.hpp +4 -2
  243. data/src/cxx_supportlib/vendor-modified/boost/intrusive/avl_set.hpp +99 -12
  244. data/src/cxx_supportlib/vendor-modified/boost/intrusive/avl_set_hook.hpp +4 -2
  245. data/src/cxx_supportlib/vendor-modified/boost/intrusive/avltree.hpp +35 -4
  246. data/src/cxx_supportlib/vendor-modified/boost/intrusive/avltree_algorithms.hpp +37 -6
  247. data/src/cxx_supportlib/vendor-modified/boost/intrusive/bs_set.hpp +95 -8
  248. data/src/cxx_supportlib/vendor-modified/boost/intrusive/bs_set_hook.hpp +4 -2
  249. data/src/cxx_supportlib/vendor-modified/boost/intrusive/bstree.hpp +209 -72
  250. data/src/cxx_supportlib/vendor-modified/boost/intrusive/bstree_algorithms.hpp +86 -20
  251. data/src/cxx_supportlib/vendor-modified/boost/intrusive/circular_list_algorithms.hpp +11 -11
  252. data/src/cxx_supportlib/vendor-modified/boost/intrusive/circular_slist_algorithms.hpp +6 -6
  253. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/algo_type.hpp +4 -1
  254. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/any_node_and_algorithms.hpp +58 -45
  255. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/avltree_node.hpp +27 -26
  256. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/bstree_algorithms_base.hpp +2 -2
  257. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/common_slist_algorithms.hpp +7 -7
  258. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/config_begin.hpp +8 -3
  259. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/default_header_holder.hpp +4 -3
  260. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/ebo_functor_holder.hpp +27 -26
  261. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/equal_to_value.hpp +3 -1
  262. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/exception_disposer.hpp +4 -2
  263. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/generic_hook.hpp +9 -7
  264. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/has_member_function_callable_with.hpp +83 -57
  265. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/hashtable_node.hpp +30 -30
  266. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/hook_traits.hpp +9 -8
  267. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/iiterator.hpp +8 -7
  268. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/iterator.hpp +16 -15
  269. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/key_nodeptr_comp.hpp +70 -44
  270. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/list_iterator.hpp +22 -21
  271. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/list_node.hpp +7 -6
  272. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/parent_from_member.hpp +5 -4
  273. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/rbtree_node.hpp +29 -28
  274. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/reverse_iterator.hpp +33 -12
  275. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/size_holder.hpp +19 -12
  276. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/slist_iterator.hpp +21 -20
  277. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/slist_node.hpp +4 -3
  278. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/to_raw_pointer.hpp +3 -2
  279. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/transform_iterator.hpp +23 -22
  280. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_iterator.hpp +23 -22
  281. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_node.hpp +10 -9
  282. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_value_compare.hpp +103 -29
  283. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/workaround.hpp +15 -0
  284. data/src/cxx_supportlib/vendor-modified/boost/intrusive/hashtable.hpp +295 -211
  285. data/src/cxx_supportlib/vendor-modified/boost/intrusive/linear_slist_algorithms.hpp +2 -2
  286. data/src/cxx_supportlib/vendor-modified/boost/intrusive/list.hpp +20 -7
  287. data/src/cxx_supportlib/vendor-modified/boost/intrusive/list_hook.hpp +4 -2
  288. data/src/cxx_supportlib/vendor-modified/boost/intrusive/member_value_traits.hpp +5 -4
  289. data/src/cxx_supportlib/vendor-modified/boost/intrusive/options.hpp +4 -4
  290. data/src/cxx_supportlib/vendor-modified/boost/intrusive/parent_from_member.hpp +3 -2
  291. data/src/cxx_supportlib/vendor-modified/boost/intrusive/pointer_plus_bits.hpp +4 -4
  292. data/src/cxx_supportlib/vendor-modified/boost/intrusive/pointer_traits.hpp +4 -4
  293. data/src/cxx_supportlib/vendor-modified/boost/intrusive/priority_compare.hpp +22 -4
  294. data/src/cxx_supportlib/vendor-modified/boost/intrusive/rbtree.hpp +36 -4
  295. data/src/cxx_supportlib/vendor-modified/boost/intrusive/rbtree_algorithms.hpp +43 -13
  296. data/src/cxx_supportlib/vendor-modified/boost/intrusive/set.hpp +95 -8
  297. data/src/cxx_supportlib/vendor-modified/boost/intrusive/set_hook.hpp +4 -2
  298. data/src/cxx_supportlib/vendor-modified/boost/intrusive/sg_set.hpp +96 -12
  299. data/src/cxx_supportlib/vendor-modified/boost/intrusive/sgtree.hpp +102 -5
  300. data/src/cxx_supportlib/vendor-modified/boost/intrusive/sgtree_algorithms.hpp +48 -4
  301. data/src/cxx_supportlib/vendor-modified/boost/intrusive/slist.hpp +20 -11
  302. data/src/cxx_supportlib/vendor-modified/boost/intrusive/slist_hook.hpp +9 -2
  303. data/src/cxx_supportlib/vendor-modified/boost/intrusive/splay_set.hpp +95 -8
  304. data/src/cxx_supportlib/vendor-modified/boost/intrusive/splaytree.hpp +36 -4
  305. data/src/cxx_supportlib/vendor-modified/boost/intrusive/splaytree_algorithms.hpp +27 -0
  306. data/src/cxx_supportlib/vendor-modified/boost/intrusive/treap.hpp +167 -23
  307. data/src/cxx_supportlib/vendor-modified/boost/intrusive/treap_algorithms.hpp +28 -0
  308. data/src/cxx_supportlib/vendor-modified/boost/intrusive/treap_set.hpp +100 -46
  309. data/src/cxx_supportlib/vendor-modified/boost/intrusive/trivial_value_traits.hpp +5 -4
  310. data/src/cxx_supportlib/vendor-modified/boost/intrusive/unordered_set.hpp +37 -27
  311. data/src/cxx_supportlib/vendor-modified/boost/intrusive/unordered_set_hook.hpp +30 -14
  312. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast.hpp +1 -1
  313. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_lexical_streams.hpp +35 -36
  314. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_numeric.hpp +6 -28
  315. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/try_lexical_convert.hpp +20 -5
  316. data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/posix_api.cpp +4 -2
  317. data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/regex.cpp +3 -1
  318. data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/pthread/once.cpp +5 -0
  319. data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/pthread/thread.cpp +11 -7
  320. data/src/cxx_supportlib/vendor-modified/boost/math/policies/policy.hpp +1 -3
  321. data/src/cxx_supportlib/vendor-modified/boost/math/special_functions/fpclassify.hpp +5 -1
  322. data/src/cxx_supportlib/vendor-modified/boost/math/special_functions/math_fwd.hpp +11 -0
  323. data/src/cxx_supportlib/vendor-modified/boost/math/tools/config.hpp +10 -2
  324. data/src/cxx_supportlib/vendor-modified/boost/move/adl_move_swap.hpp +40 -7
  325. data/src/cxx_supportlib/vendor-modified/boost/move/algo/adaptive_merge.hpp +67 -0
  326. data/src/cxx_supportlib/vendor-modified/boost/move/algo/adaptive_sort.hpp +63 -0
  327. data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/adaptive_sort_merge.hpp +2437 -0
  328. data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/basic_op.hpp +121 -0
  329. data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/insertion_sort.hpp +127 -0
  330. data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/merge.hpp +637 -0
  331. data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/merge_sort.hpp +139 -0
  332. data/src/cxx_supportlib/vendor-modified/boost/move/algo/move.hpp +155 -0
  333. data/src/cxx_supportlib/vendor-modified/boost/move/algorithm.hpp +1 -116
  334. data/src/cxx_supportlib/vendor-modified/boost/move/core.hpp +14 -13
  335. data/src/cxx_supportlib/vendor-modified/boost/move/default_delete.hpp +17 -1
  336. data/src/cxx_supportlib/vendor-modified/boost/move/detail/config_begin.hpp +2 -0
  337. data/src/cxx_supportlib/vendor-modified/boost/move/detail/destruct_n.hpp +67 -0
  338. data/src/cxx_supportlib/vendor-modified/boost/move/detail/fwd_macros.hpp +227 -32
  339. data/src/cxx_supportlib/vendor-modified/boost/move/detail/iterator_traits.hpp +4 -0
  340. data/src/cxx_supportlib/vendor-modified/boost/move/detail/meta_utils.hpp +30 -9
  341. data/src/cxx_supportlib/vendor-modified/boost/move/detail/meta_utils_core.hpp +12 -0
  342. data/src/cxx_supportlib/vendor-modified/boost/move/detail/move_helpers.hpp +84 -80
  343. data/src/cxx_supportlib/vendor-modified/boost/move/detail/placement_new.hpp +30 -0
  344. data/src/cxx_supportlib/vendor-modified/boost/move/detail/reverse_iterator.hpp +171 -0
  345. data/src/cxx_supportlib/vendor-modified/boost/move/detail/type_traits.hpp +14 -20
  346. data/src/cxx_supportlib/vendor-modified/boost/move/detail/unique_ptr_meta_utils.hpp +1 -1
  347. data/src/cxx_supportlib/vendor-modified/boost/move/detail/workaround.hpp +14 -0
  348. data/src/cxx_supportlib/vendor-modified/boost/move/iterator.hpp +32 -33
  349. data/src/cxx_supportlib/vendor-modified/boost/move/make_unique.hpp +2 -1
  350. data/src/cxx_supportlib/vendor-modified/boost/move/unique_ptr.hpp +49 -49
  351. data/src/cxx_supportlib/vendor-modified/boost/move/utility.hpp +8 -7
  352. data/src/cxx_supportlib/vendor-modified/boost/move/utility_core.hpp +17 -16
  353. data/src/cxx_supportlib/vendor-modified/boost/mpl/print.hpp +3 -0
  354. data/src/cxx_supportlib/vendor-modified/boost/none.hpp +1 -1
  355. data/src/cxx_supportlib/vendor-modified/boost/none_t.hpp +2 -3
  356. data/src/cxx_supportlib/vendor-modified/boost/operators.hpp +197 -255
  357. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/old_optional_implementation.hpp +1059 -0
  358. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_aligned_storage.hpp +75 -0
  359. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_config.hpp +116 -0
  360. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_factory_support.hpp +36 -0
  361. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_reference_spec.hpp +253 -0
  362. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_relops.hpp +196 -0
  363. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_swap.hpp +117 -0
  364. data/src/cxx_supportlib/vendor-modified/boost/optional/optional.hpp +372 -554
  365. data/src/cxx_supportlib/vendor-modified/boost/optional/optional_fwd.hpp +12 -1
  366. data/src/cxx_supportlib/vendor-modified/boost/pool/detail/mutex.hpp +15 -7
  367. data/src/cxx_supportlib/vendor-modified/boost/pool/pool_alloc.hpp +24 -0
  368. data/src/cxx_supportlib/vendor-modified/boost/predef/compiler/intel.h +9 -2
  369. data/src/cxx_supportlib/vendor-modified/boost/predef/compiler/visualc.h +15 -1
  370. data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd.h +16 -4
  371. data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd/x86.h +3 -3
  372. data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd/x86_amd.h +4 -4
  373. data/src/cxx_supportlib/vendor-modified/boost/predef/hardware/simd/x86_amd/versions.h +4 -4
  374. data/src/cxx_supportlib/vendor-modified/boost/predef/os/cygwin.h +1 -1
  375. data/src/cxx_supportlib/vendor-modified/boost/predef/version.h +2 -2
  376. data/src/cxx_supportlib/vendor-modified/boost/predef/version_number.h +20 -1
  377. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/cat.hpp +1 -1
  378. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/config/config.hpp +6 -6
  379. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/seq/detail/binary_transform.hpp +5 -6
  380. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/seq/detail/to_list_msvc.hpp +55 -0
  381. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/seq/to_list.hpp +12 -0
  382. data/src/cxx_supportlib/vendor-modified/boost/range/const_iterator.hpp +4 -4
  383. data/src/cxx_supportlib/vendor-modified/boost/range/size_type.hpp +0 -5
  384. data/src/cxx_supportlib/vendor-modified/boost/regex/concepts.hpp +16 -16
  385. data/src/cxx_supportlib/vendor-modified/boost/regex/config.hpp +4 -4
  386. data/src/cxx_supportlib/vendor-modified/boost/regex/pending/unicode_iterator.hpp +3 -0
  387. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/basic_regex_creator.hpp +102 -87
  388. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/basic_regex_parser.hpp +45 -21
  389. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/cpp_regex_traits.hpp +4 -4
  390. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/fileiter.hpp +2 -2
  391. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/instances.hpp +1 -1
  392. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/match_flags.hpp +14 -2
  393. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/mem_block_cache.hpp +46 -0
  394. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher.hpp +5 -2
  395. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_common.hpp +5 -14
  396. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_non_recursive.hpp +116 -13
  397. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_recursive.hpp +34 -0
  398. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_format.hpp +2 -2
  399. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_traits.hpp +1 -1
  400. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_traits_defaults.hpp +3 -3
  401. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_workaround.hpp +1 -0
  402. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/w32_regex_traits.hpp +2 -2
  403. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/allocate_shared_array.hpp +1004 -159
  404. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/bad_weak_ptr.hpp +9 -0
  405. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/atomic_count.hpp +3 -0
  406. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/shared_count.hpp +4 -58
  407. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base.hpp +5 -2
  408. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_clang.hpp +9 -0
  409. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_impl.hpp +0 -8
  410. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_has_sync.hpp +3 -3
  411. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_noexcept.hpp +30 -0
  412. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/spinlock.hpp +3 -0
  413. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/enable_shared_from_this.hpp +5 -4
  414. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/intrusive_ptr.hpp +28 -3
  415. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/intrusive_ref_counter.hpp +187 -0
  416. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/make_shared_array.hpp +52 -144
  417. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/make_shared_object.hpp +120 -450
  418. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/scoped_array.hpp +2 -1
  419. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/scoped_ptr.hpp +2 -1
  420. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/shared_array.hpp +7 -6
  421. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/shared_ptr.hpp +70 -8
  422. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/weak_ptr.hpp +6 -5
  423. data/src/cxx_supportlib/vendor-modified/boost/system/error_code.hpp +9 -8
  424. data/src/cxx_supportlib/vendor-modified/boost/system/system_error.hpp +3 -3
  425. data/src/cxx_supportlib/vendor-modified/boost/thread/barrier.hpp +5 -4
  426. data/src/cxx_supportlib/vendor-modified/boost/thread/completion_latch.hpp +0 -1
  427. data/src/cxx_supportlib/vendor-modified/boost/thread/concurrent_queues/queue_views.hpp +0 -11
  428. data/src/cxx_supportlib/vendor-modified/boost/thread/concurrent_queues/sync_timed_queue.hpp +6 -4
  429. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/config.hpp +11 -2
  430. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/thread.hpp +11 -4
  431. data/src/cxx_supportlib/vendor-modified/boost/thread/exceptions.hpp +8 -8
  432. data/src/cxx_supportlib/vendor-modified/boost/thread/executors/executor.hpp +1 -1
  433. data/src/cxx_supportlib/vendor-modified/boost/thread/executors/generic_executor_ref.hpp +5 -5
  434. data/src/cxx_supportlib/vendor-modified/boost/thread/executors/loop_executor.hpp +22 -18
  435. data/src/cxx_supportlib/vendor-modified/boost/thread/future.hpp +163 -55
  436. data/src/cxx_supportlib/vendor-modified/boost/thread/futures/launch.hpp +1 -0
  437. data/src/cxx_supportlib/vendor-modified/boost/thread/futures/wait_for_all.hpp +1 -1
  438. data/src/cxx_supportlib/vendor-modified/boost/thread/lock_types.hpp +9 -9
  439. data/src/cxx_supportlib/vendor-modified/boost/thread/locks.hpp +1 -0
  440. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/condition_variable.hpp +6 -7
  441. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/condition_variable_fwd.hpp +17 -2
  442. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/shared_mutex.hpp +2 -2
  443. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/thread_data.hpp +5 -5
  444. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/timespec.hpp +29 -0
  445. data/src/cxx_supportlib/vendor-modified/boost/thread/scoped_thread.hpp +23 -18
  446. data/src/cxx_supportlib/vendor-modified/boost/thread/synchronized_value.hpp +6 -6
  447. data/src/cxx_supportlib/vendor-modified/boost/thread/thread_functors.hpp +19 -4
  448. data/src/cxx_supportlib/vendor-modified/boost/thread/thread_guard.hpp +3 -3
  449. data/src/cxx_supportlib/vendor-modified/boost/thread/user_scheduler.hpp +1 -1
  450. data/src/cxx_supportlib/vendor-modified/boost/type_index.hpp +265 -0
  451. data/src/cxx_supportlib/vendor-modified/boost/type_index/stl_type_index.hpp +272 -0
  452. data/src/cxx_supportlib/vendor-modified/boost/type_index/type_index_facade.hpp +300 -0
  453. data/src/cxx_supportlib/vendor-modified/boost/type_traits/add_reference.hpp +3 -3
  454. data/src/cxx_supportlib/vendor-modified/boost/type_traits/aligned_storage.hpp +6 -6
  455. data/src/cxx_supportlib/vendor-modified/boost/type_traits/common_type.hpp +1 -0
  456. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/common_arithmetic_type.hpp +9 -3
  457. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/mp_defer.hpp +3 -3
  458. data/src/cxx_supportlib/vendor-modified/boost/type_traits/extent.hpp +1 -0
  459. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_nothrow_assign.hpp +2 -1
  460. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_nothrow_constructor.hpp +2 -1
  461. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_nothrow_destructor.hpp +1 -1
  462. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_assign.hpp +2 -1
  463. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_copy.hpp +1 -0
  464. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_destructor.hpp +1 -1
  465. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_move_assign.hpp +1 -0
  466. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_move_constructor.hpp +1 -0
  467. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_abstract.hpp +1 -0
  468. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_array.hpp +1 -1
  469. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_assignable.hpp +1 -0
  470. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_const.hpp +2 -1
  471. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_default_constructible.hpp +21 -1
  472. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_destructible.hpp +1 -0
  473. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_nothrow_move_assignable.hpp +1 -1
  474. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_nothrow_move_constructible.hpp +2 -1
  475. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_pod.hpp +1 -0
  476. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_rvalue_reference.hpp +1 -1
  477. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_virtual_base_of.hpp +1 -1
  478. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_volatile.hpp +2 -1
  479. data/src/cxx_supportlib/vendor-modified/boost/type_traits/make_void.hpp +52 -0
  480. data/src/cxx_supportlib/vendor-modified/boost/type_traits/rank.hpp +1 -0
  481. data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_all_extents.hpp +1 -1
  482. data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_const.hpp +1 -1
  483. data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_cv.hpp +1 -1
  484. data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_extent.hpp +1 -1
  485. data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_pointer.hpp +1 -1
  486. data/src/cxx_supportlib/vendor-modified/boost/type_traits/remove_volatile.hpp +1 -1
  487. data/src/cxx_supportlib/vendor-modified/boost/type_traits/type_with_alignment.hpp +1 -1
  488. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/fwd.hpp +40 -6
  489. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/implementation.hpp +4986 -0
  490. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/map.hpp +107 -0
  491. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/set.hpp +105 -0
  492. data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_map.hpp +1814 -1255
  493. data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_map_fwd.hpp +41 -45
  494. data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_set.hpp +1498 -1161
  495. data/src/cxx_supportlib/vendor-modified/boost/unordered/unordered_set_fwd.hpp +40 -44
  496. data/src/cxx_supportlib/vendor-modified/boost/utility.hpp +2 -2
  497. data/src/cxx_supportlib/vendor-modified/boost/utility/base_from_member.hpp +7 -6
  498. data/src/cxx_supportlib/vendor-modified/boost/utility/compare_pointees.hpp +10 -2
  499. data/src/cxx_supportlib/vendor-modified/boost/utility/string_ref.hpp +39 -22
  500. data/src/cxx_supportlib/vendor-modified/boost/utility/string_view.hpp +690 -0
  501. data/src/cxx_supportlib/vendor-modified/boost/utility/string_view_fwd.hpp +39 -0
  502. data/src/cxx_supportlib/vendor-modified/boost/version.hpp +2 -2
  503. data/src/helper-scripts/crash-watch.rb +3 -0
  504. data/src/ruby_supportlib/phusion_passenger.rb +1 -1
  505. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +1 -0
  506. data/src/ruby_supportlib/phusion_passenger/packaging.rb +2 -12
  507. metadata +77 -38
  508. data/dev/ci/inituidgid +0 -24
  509. data/dev/ci/run_jenkins.sh +0 -70
  510. data/dev/ci/run_travis.sh +0 -314
  511. data/doc/Design and Architecture.html +0 -2421
  512. data/doc/Design and Architecture.txt +0 -511
  513. data/doc/Security of user switching support.html +0 -1833
  514. data/doc/Users guide Apache.html +0 -3101
  515. data/doc/Users guide Apache.idmap.txt +0 -451
  516. data/doc/Users guide Apache.txt +0 -534
  517. data/doc/Users guide Nginx.html +0 -3026
  518. data/doc/Users guide Nginx.idmap.txt +0 -431
  519. data/doc/Users guide Nginx.txt +0 -451
  520. data/doc/Users guide Standalone.html +0 -2092
  521. data/doc/Users guide Standalone.idmap.txt +0 -137
  522. data/doc/Users guide Standalone.txt +0 -81
  523. data/doc/Users guide.html +0 -1606
  524. data/doc/Users guide.txt +0 -8
  525. data/src/cxx_supportlib/vendor-modified/boost/align/align.hpp +0 -20
  526. data/src/cxx_supportlib/vendor-modified/boost/align/detail/address.hpp +0 -29
  527. data/src/cxx_supportlib/vendor-modified/boost/align/detail/align.hpp +0 -40
  528. data/src/cxx_supportlib/vendor-modified/boost/align/detail/align_cxx11.hpp +0 -22
  529. data/src/cxx_supportlib/vendor-modified/boost/align/detail/is_alignment.hpp +0 -29
  530. data/src/cxx_supportlib/vendor-modified/boost/container/detail/hash_table.hpp +0 -383
  531. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_allocator.hpp +0 -318
  532. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_count_impl.hpp +0 -67
  533. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_traits.hpp +0 -60
  534. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/array_utility.hpp +0 -214
  535. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_if_array.hpp +0 -34
  536. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/allocate.hpp +0 -1128
  537. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/buckets.hpp +0 -928
  538. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/equivalent.hpp +0 -686
  539. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/extract_key.hpp +0 -188
  540. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/table.hpp +0 -873
  541. data/src/cxx_supportlib/vendor-modified/boost/unordered/detail/unique.hpp +0 -628
  542. 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>(v);
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
- # define BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
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
- #endif // BOOST_MATH_TOOLS_CONFIG_HPP
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