1134723edSLouis Dionne //===----------------------------------------------------------------------===// 2134723edSLouis Dionne // 3134723edSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4134723edSLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 5134723edSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6134723edSLouis Dionne // 7134723edSLouis Dionne //===----------------------------------------------------------------------===// 8134723edSLouis Dionne 9134723edSLouis Dionne #ifndef _LIBCPP___ALGORITHM_SHUFFLE_H 10134723edSLouis Dionne #define _LIBCPP___ALGORITHM_SHUFFLE_H 11134723edSLouis Dionne 12a7c3379cSKonstantin Varlamov #include <__algorithm/iterator_operations.h> 13134723edSLouis Dionne #include <__config> 14*e99c4906SNikolas Klauser #include <__cstddef/ptrdiff_t.h> 15134723edSLouis Dionne #include <__iterator/iterator_traits.h> 16134723edSLouis Dionne #include <__random/uniform_int_distribution.h> 17a7c3379cSKonstantin Varlamov #include <__utility/forward.h> 18a7c3379cSKonstantin Varlamov #include <__utility/move.h> 19430b397fSNikolas Klauser #include <__utility/swap.h> 20134723edSLouis Dionne #include <cstdint> 21134723edSLouis Dionne 22134723edSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23134723edSLouis Dionne # pragma GCC system_header 24134723edSLouis Dionne #endif 25134723edSLouis Dionne 26134723edSLouis Dionne _LIBCPP_PUSH_MACROS 27134723edSLouis Dionne #include <__undef_macros> 28134723edSLouis Dionne 29134723edSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 30134723edSLouis Dionne 31f1ea0b11SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_randomizer { 32a45d2287SDanila Kutenin public: 3383ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI __libcpp_debug_randomizer() { 3484fc2c3cSNikolas Klauser __state_ = __seed(); 3584fc2c3cSNikolas Klauser __inc_ = __state_ + 0xda3e39cb94b95bdbULL; 3684fc2c3cSNikolas Klauser __inc_ = (__inc_ << 1) | 1; 37a45d2287SDanila Kutenin } 38a45d2287SDanila Kutenin typedef uint_fast32_t result_type; 39a45d2287SDanila Kutenin 40a45d2287SDanila Kutenin static const result_type _Min = 0; 41a45d2287SDanila Kutenin static const result_type _Max = 0xFFFFFFFF; 42a45d2287SDanila Kutenin 43a45d2287SDanila Kutenin _LIBCPP_HIDE_FROM_ABI result_type operator()() { 4484fc2c3cSNikolas Klauser uint_fast64_t __oldstate = __state_; 4584fc2c3cSNikolas Klauser __state_ = __oldstate * 6364136223846793005ULL + __inc_; 46a45d2287SDanila Kutenin return __oldstate >> 32; 47a45d2287SDanila Kutenin } 48a45d2287SDanila Kutenin 49a45d2287SDanila Kutenin static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; } 50a45d2287SDanila Kutenin static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; } 51a45d2287SDanila Kutenin 52a45d2287SDanila Kutenin private: 5384fc2c3cSNikolas Klauser uint_fast64_t __state_; 5484fc2c3cSNikolas Klauser uint_fast64_t __inc_; 55a45d2287SDanila Kutenin _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() { 56a45d2287SDanila Kutenin #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED 57a45d2287SDanila Kutenin return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED; 58a45d2287SDanila Kutenin #else 59a45d2287SDanila Kutenin static char __x; 60a45d2287SDanila Kutenin return reinterpret_cast<uintptr_t>(&__x); 61a45d2287SDanila Kutenin #endif 62a45d2287SDanila Kutenin } 63a45d2287SDanila Kutenin }; 64a45d2287SDanila Kutenin 659783f28cSLouis Dionne #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) || defined(_LIBCPP_BUILDING_LIBRARY) 66f1ea0b11SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI __rs_default; 67134723edSLouis Dionne 68f1ea0b11SNikolas Klauser _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); 69134723edSLouis Dionne 709783f28cSLouis Dionne class _LIBCPP_EXPORTED_FROM_ABI __rs_default { 71134723edSLouis Dionne static unsigned __c_; 72134723edSLouis Dionne 73134723edSLouis Dionne __rs_default(); 749783f28cSLouis Dionne 75134723edSLouis Dionne public: 76134723edSLouis Dionne typedef uint_fast32_t result_type; 77134723edSLouis Dionne 78134723edSLouis Dionne static const result_type _Min = 0; 79134723edSLouis Dionne static const result_type _Max = 0xFFFFFFFF; 80134723edSLouis Dionne 81134723edSLouis Dionne __rs_default(const __rs_default&); 82134723edSLouis Dionne ~__rs_default(); 83134723edSLouis Dionne 84134723edSLouis Dionne result_type operator()(); 85134723edSLouis Dionne 8683ce1397SNikolas Klauser static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; } 8783ce1397SNikolas Klauser static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; } 88134723edSLouis Dionne 89f1ea0b11SNikolas Klauser friend _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); 90134723edSLouis Dionne }; 91134723edSLouis Dionne 92f1ea0b11SNikolas Klauser _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); 93134723edSLouis Dionne 94134723edSLouis Dionne template <class _RandomAccessIterator> 9580c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void 969783f28cSLouis Dionne random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) { 97134723edSLouis Dionne typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 98134723edSLouis Dionne typedef uniform_int_distribution<ptrdiff_t> _Dp; 99134723edSLouis Dionne typedef typename _Dp::param_type _Pp; 100134723edSLouis Dionne difference_type __d = __last - __first; 1019783f28cSLouis Dionne if (__d > 1) { 102134723edSLouis Dionne _Dp __uid; 103134723edSLouis Dionne __rs_default __g = __rs_get(); 1049783f28cSLouis Dionne for (--__last, (void)--__d; __first < __last; ++__first, (void)--__d) { 105134723edSLouis Dionne difference_type __i = __uid(__g, _Pp(0, __d)); 106134723edSLouis Dionne if (__i != difference_type(0)) 107134723edSLouis Dionne swap(*__first, *(__first + __i)); 108134723edSLouis Dionne } 109134723edSLouis Dionne } 110134723edSLouis Dionne } 111134723edSLouis Dionne 112134723edSLouis Dionne template <class _RandomAccessIterator, class _RandomNumberGenerator> 11380c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void 1149783f28cSLouis Dionne random_shuffle(_RandomAccessIterator __first, 1159783f28cSLouis Dionne _RandomAccessIterator __last, 116134723edSLouis Dionne # ifndef _LIBCPP_CXX03_LANG 117134723edSLouis Dionne _RandomNumberGenerator&& __rand) 118134723edSLouis Dionne # else 119134723edSLouis Dionne _RandomNumberGenerator& __rand) 120134723edSLouis Dionne # endif 121134723edSLouis Dionne { 122134723edSLouis Dionne typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 123134723edSLouis Dionne difference_type __d = __last - __first; 1249783f28cSLouis Dionne if (__d > 1) { 1259783f28cSLouis Dionne for (--__last; __first < __last; ++__first, (void)--__d) { 126134723edSLouis Dionne difference_type __i = __rand(__d); 127134723edSLouis Dionne if (__i != difference_type(0)) 128134723edSLouis Dionne swap(*__first, *(__first + __i)); 129134723edSLouis Dionne } 130134723edSLouis Dionne } 131134723edSLouis Dionne } 132134723edSLouis Dionne #endif 133134723edSLouis Dionne 13414cf74d6SKonstantin Varlamov template <class _AlgPolicy, class _RandomAccessIterator, class _Sentinel, class _UniformRandomNumberGenerator> 1359783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator 1369783f28cSLouis Dionne __shuffle(_RandomAccessIterator __first, _Sentinel __last_sentinel, _UniformRandomNumberGenerator&& __g) { 137134723edSLouis Dionne typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 138134723edSLouis Dionne typedef uniform_int_distribution<ptrdiff_t> _Dp; 139134723edSLouis Dionne typedef typename _Dp::param_type _Pp; 14014cf74d6SKonstantin Varlamov 14114cf74d6SKonstantin Varlamov auto __original_last = _IterOps<_AlgPolicy>::next(__first, __last_sentinel); 14214cf74d6SKonstantin Varlamov auto __last = __original_last; 143134723edSLouis Dionne difference_type __d = __last - __first; 1449783f28cSLouis Dionne if (__d > 1) { 145134723edSLouis Dionne _Dp __uid; 1469783f28cSLouis Dionne for (--__last, (void)--__d; __first < __last; ++__first, (void)--__d) { 147134723edSLouis Dionne difference_type __i = __uid(__g, _Pp(0, __d)); 148134723edSLouis Dionne if (__i != difference_type(0)) 149a7c3379cSKonstantin Varlamov _IterOps<_AlgPolicy>::iter_swap(__first, __first + __i); 150134723edSLouis Dionne } 151134723edSLouis Dionne } 15214cf74d6SKonstantin Varlamov 15314cf74d6SKonstantin Varlamov return __original_last; 154134723edSLouis Dionne } 155134723edSLouis Dionne 156a7c3379cSKonstantin Varlamov template <class _RandomAccessIterator, class _UniformRandomNumberGenerator> 15780c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI void 15880c7e93aSNikolas Klauser shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _UniformRandomNumberGenerator&& __g) { 15914cf74d6SKonstantin Varlamov (void)std::__shuffle<_ClassicAlgPolicy>( 160a7c3379cSKonstantin Varlamov std::move(__first), std::move(__last), std::forward<_UniformRandomNumberGenerator>(__g)); 161a7c3379cSKonstantin Varlamov } 162a7c3379cSKonstantin Varlamov 163134723edSLouis Dionne _LIBCPP_END_NAMESPACE_STD 164134723edSLouis Dionne 165134723edSLouis Dionne _LIBCPP_POP_MACROS 166134723edSLouis Dionne 167134723edSLouis Dionne #endif // _LIBCPP___ALGORITHM_SHUFFLE_H 168