1fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #ifndef _LIBCPP___ALGORITHM_SHUFFLE_H 10fe6060f1SDimitry Andric #define _LIBCPP___ALGORITHM_SHUFFLE_H 11fe6060f1SDimitry Andric 12fcaf7f86SDimitry Andric #include <__algorithm/iterator_operations.h> 13fe6060f1SDimitry Andric #include <__config> 14fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 15fe6060f1SDimitry Andric #include <__random/uniform_int_distribution.h> 16fcaf7f86SDimitry Andric #include <__utility/forward.h> 17fcaf7f86SDimitry Andric #include <__utility/move.h> 18bdd1243dSDimitry Andric #include <__utility/swap.h> 19fe6060f1SDimitry Andric #include <cstddef> 20fe6060f1SDimitry Andric #include <cstdint> 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 23fe6060f1SDimitry Andric # pragma GCC system_header 24fe6060f1SDimitry Andric #endif 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric _LIBCPP_PUSH_MACROS 27fe6060f1SDimitry Andric #include <__undef_macros> 28fe6060f1SDimitry Andric 29fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 30fe6060f1SDimitry Andric 31*06c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_randomizer { 32349cc55cSDimitry Andric public: 33*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __libcpp_debug_randomizer() { 34bdd1243dSDimitry Andric __state_ = __seed(); 35bdd1243dSDimitry Andric __inc_ = __state_ + 0xda3e39cb94b95bdbULL; 36bdd1243dSDimitry Andric __inc_ = (__inc_ << 1) | 1; 37349cc55cSDimitry Andric } 38349cc55cSDimitry Andric typedef uint_fast32_t result_type; 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric static const result_type _Min = 0; 41349cc55cSDimitry Andric static const result_type _Max = 0xFFFFFFFF; 42349cc55cSDimitry Andric 43349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type operator()() { 44bdd1243dSDimitry Andric uint_fast64_t __oldstate = __state_; 45bdd1243dSDimitry Andric __state_ = __oldstate * 6364136223846793005ULL + __inc_; 46349cc55cSDimitry Andric return __oldstate >> 32; 47349cc55cSDimitry Andric } 48349cc55cSDimitry Andric 49349cc55cSDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; } 50349cc55cSDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; } 51349cc55cSDimitry Andric 52349cc55cSDimitry Andric private: 53bdd1243dSDimitry Andric uint_fast64_t __state_; 54bdd1243dSDimitry Andric uint_fast64_t __inc_; 55349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() { 56349cc55cSDimitry Andric #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED 57349cc55cSDimitry Andric return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED; 58349cc55cSDimitry Andric #else 59349cc55cSDimitry Andric static char __x; 60349cc55cSDimitry Andric return reinterpret_cast<uintptr_t>(&__x); 61349cc55cSDimitry Andric #endif 62349cc55cSDimitry Andric } 63349cc55cSDimitry Andric }; 64fe6060f1SDimitry Andric 65fe6060f1SDimitry Andric #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ 66fe6060f1SDimitry Andric || defined(_LIBCPP_BUILDING_LIBRARY) 67*06c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI __rs_default; 68fe6060f1SDimitry Andric 69*06c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); 70fe6060f1SDimitry Andric 71*06c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI __rs_default 72fe6060f1SDimitry Andric { 73fe6060f1SDimitry Andric static unsigned __c_; 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric __rs_default(); 76fe6060f1SDimitry Andric public: 77fe6060f1SDimitry Andric typedef uint_fast32_t result_type; 78fe6060f1SDimitry Andric 79fe6060f1SDimitry Andric static const result_type _Min = 0; 80fe6060f1SDimitry Andric static const result_type _Max = 0xFFFFFFFF; 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric __rs_default(const __rs_default&); 83fe6060f1SDimitry Andric ~__rs_default(); 84fe6060f1SDimitry Andric 85fe6060f1SDimitry Andric result_type operator()(); 86fe6060f1SDimitry Andric 87*06c3fb27SDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() {return _Min;} 88*06c3fb27SDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() {return _Max;} 89fe6060f1SDimitry Andric 90*06c3fb27SDimitry Andric friend _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); 91fe6060f1SDimitry Andric }; 92fe6060f1SDimitry Andric 93*06c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); 94fe6060f1SDimitry Andric 95fe6060f1SDimitry Andric template <class _RandomAccessIterator> 96bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void 97fe6060f1SDimitry Andric random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) 98fe6060f1SDimitry Andric { 99fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 100fe6060f1SDimitry Andric typedef uniform_int_distribution<ptrdiff_t> _Dp; 101fe6060f1SDimitry Andric typedef typename _Dp::param_type _Pp; 102fe6060f1SDimitry Andric difference_type __d = __last - __first; 103fe6060f1SDimitry Andric if (__d > 1) 104fe6060f1SDimitry Andric { 105fe6060f1SDimitry Andric _Dp __uid; 106fe6060f1SDimitry Andric __rs_default __g = __rs_get(); 107fe6060f1SDimitry Andric for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) 108fe6060f1SDimitry Andric { 109fe6060f1SDimitry Andric difference_type __i = __uid(__g, _Pp(0, __d)); 110fe6060f1SDimitry Andric if (__i != difference_type(0)) 111fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 112fe6060f1SDimitry Andric } 113fe6060f1SDimitry Andric } 114fe6060f1SDimitry Andric } 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric template <class _RandomAccessIterator, class _RandomNumberGenerator> 117bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void 118fe6060f1SDimitry Andric random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, 119fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 120fe6060f1SDimitry Andric _RandomNumberGenerator&& __rand) 121fe6060f1SDimitry Andric #else 122fe6060f1SDimitry Andric _RandomNumberGenerator& __rand) 123fe6060f1SDimitry Andric #endif 124fe6060f1SDimitry Andric { 125fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 126fe6060f1SDimitry Andric difference_type __d = __last - __first; 127fe6060f1SDimitry Andric if (__d > 1) 128fe6060f1SDimitry Andric { 129fe6060f1SDimitry Andric for (--__last; __first < __last; ++__first, (void) --__d) 130fe6060f1SDimitry Andric { 131fe6060f1SDimitry Andric difference_type __i = __rand(__d); 132fe6060f1SDimitry Andric if (__i != difference_type(0)) 133fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 134fe6060f1SDimitry Andric } 135fe6060f1SDimitry Andric } 136fe6060f1SDimitry Andric } 137fe6060f1SDimitry Andric #endif 138fe6060f1SDimitry Andric 139fcaf7f86SDimitry Andric template <class _AlgPolicy, class _RandomAccessIterator, class _Sentinel, class _UniformRandomNumberGenerator> 140bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator __shuffle( 141fcaf7f86SDimitry Andric _RandomAccessIterator __first, _Sentinel __last_sentinel, _UniformRandomNumberGenerator&& __g) { 142fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 143fe6060f1SDimitry Andric typedef uniform_int_distribution<ptrdiff_t> _Dp; 144fe6060f1SDimitry Andric typedef typename _Dp::param_type _Pp; 145fcaf7f86SDimitry Andric 146fcaf7f86SDimitry Andric auto __original_last = _IterOps<_AlgPolicy>::next(__first, __last_sentinel); 147fcaf7f86SDimitry Andric auto __last = __original_last; 148fe6060f1SDimitry Andric difference_type __d = __last - __first; 149fe6060f1SDimitry Andric if (__d > 1) 150fe6060f1SDimitry Andric { 151fe6060f1SDimitry Andric _Dp __uid; 152fe6060f1SDimitry Andric for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) 153fe6060f1SDimitry Andric { 154fe6060f1SDimitry Andric difference_type __i = __uid(__g, _Pp(0, __d)); 155fe6060f1SDimitry Andric if (__i != difference_type(0)) 156fcaf7f86SDimitry Andric _IterOps<_AlgPolicy>::iter_swap(__first, __first + __i); 157fe6060f1SDimitry Andric } 158fe6060f1SDimitry Andric } 159fcaf7f86SDimitry Andric 160fcaf7f86SDimitry Andric return __original_last; 161fcaf7f86SDimitry Andric } 162fcaf7f86SDimitry Andric 163fcaf7f86SDimitry Andric template <class _RandomAccessIterator, class _UniformRandomNumberGenerator> 164bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI void 165bdd1243dSDimitry Andric shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _UniformRandomNumberGenerator&& __g) { 166fcaf7f86SDimitry Andric (void)std::__shuffle<_ClassicAlgPolicy>( 167fcaf7f86SDimitry Andric std::move(__first), std::move(__last), std::forward<_UniformRandomNumberGenerator>(__g)); 168fe6060f1SDimitry Andric } 169fe6060f1SDimitry Andric 170fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 171fe6060f1SDimitry Andric 172fe6060f1SDimitry Andric _LIBCPP_POP_MACROS 173fe6060f1SDimitry Andric 174fe6060f1SDimitry Andric #endif // _LIBCPP___ALGORITHM_SHUFFLE_H 175