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 12fe6060f1SDimitry Andric #include <__config> 13fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 14fe6060f1SDimitry Andric #include <__random/uniform_int_distribution.h> 15fe6060f1SDimitry Andric #include <__utility/swap.h> 16fe6060f1SDimitry Andric #include <cstddef> 17fe6060f1SDimitry Andric #include <cstdint> 18fe6060f1SDimitry Andric 19fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20fe6060f1SDimitry Andric #pragma GCC system_header 21fe6060f1SDimitry Andric #endif 22fe6060f1SDimitry Andric 23fe6060f1SDimitry Andric _LIBCPP_PUSH_MACROS 24fe6060f1SDimitry Andric #include <__undef_macros> 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 27fe6060f1SDimitry Andric 28*349cc55cSDimitry Andric class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer { 29*349cc55cSDimitry Andric public: 30*349cc55cSDimitry Andric __libcpp_debug_randomizer() { 31*349cc55cSDimitry Andric __state = __seed(); 32*349cc55cSDimitry Andric __inc = __state + 0xda3e39cb94b95bdbULL; 33*349cc55cSDimitry Andric __inc = (__inc << 1) | 1; 34*349cc55cSDimitry Andric } 35*349cc55cSDimitry Andric typedef uint_fast32_t result_type; 36*349cc55cSDimitry Andric 37*349cc55cSDimitry Andric static const result_type _Min = 0; 38*349cc55cSDimitry Andric static const result_type _Max = 0xFFFFFFFF; 39*349cc55cSDimitry Andric 40*349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type operator()() { 41*349cc55cSDimitry Andric uint_fast64_t __oldstate = __state; 42*349cc55cSDimitry Andric __state = __oldstate * 6364136223846793005ULL + __inc; 43*349cc55cSDimitry Andric return __oldstate >> 32; 44*349cc55cSDimitry Andric } 45*349cc55cSDimitry Andric 46*349cc55cSDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; } 47*349cc55cSDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; } 48*349cc55cSDimitry Andric 49*349cc55cSDimitry Andric private: 50*349cc55cSDimitry Andric uint_fast64_t __state; 51*349cc55cSDimitry Andric uint_fast64_t __inc; 52*349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() { 53*349cc55cSDimitry Andric #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED 54*349cc55cSDimitry Andric return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED; 55*349cc55cSDimitry Andric #else 56*349cc55cSDimitry Andric static char __x; 57*349cc55cSDimitry Andric return reinterpret_cast<uintptr_t>(&__x); 58*349cc55cSDimitry Andric #endif 59*349cc55cSDimitry Andric } 60*349cc55cSDimitry Andric }; 61fe6060f1SDimitry Andric 62fe6060f1SDimitry Andric #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ 63fe6060f1SDimitry Andric || defined(_LIBCPP_BUILDING_LIBRARY) 64fe6060f1SDimitry Andric class _LIBCPP_TYPE_VIS __rs_default; 65fe6060f1SDimitry Andric 66fe6060f1SDimitry Andric _LIBCPP_FUNC_VIS __rs_default __rs_get(); 67fe6060f1SDimitry Andric 68fe6060f1SDimitry Andric class _LIBCPP_TYPE_VIS __rs_default 69fe6060f1SDimitry Andric { 70fe6060f1SDimitry Andric static unsigned __c_; 71fe6060f1SDimitry Andric 72fe6060f1SDimitry Andric __rs_default(); 73fe6060f1SDimitry Andric public: 74fe6060f1SDimitry Andric typedef uint_fast32_t result_type; 75fe6060f1SDimitry Andric 76fe6060f1SDimitry Andric static const result_type _Min = 0; 77fe6060f1SDimitry Andric static const result_type _Max = 0xFFFFFFFF; 78fe6060f1SDimitry Andric 79fe6060f1SDimitry Andric __rs_default(const __rs_default&); 80fe6060f1SDimitry Andric ~__rs_default(); 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric result_type operator()(); 83fe6060f1SDimitry Andric 84fe6060f1SDimitry Andric static _LIBCPP_CONSTEXPR result_type min() {return _Min;} 85fe6060f1SDimitry Andric static _LIBCPP_CONSTEXPR result_type max() {return _Max;} 86fe6060f1SDimitry Andric 87fe6060f1SDimitry Andric friend _LIBCPP_FUNC_VIS __rs_default __rs_get(); 88fe6060f1SDimitry Andric }; 89fe6060f1SDimitry Andric 90fe6060f1SDimitry Andric _LIBCPP_FUNC_VIS __rs_default __rs_get(); 91fe6060f1SDimitry Andric 92fe6060f1SDimitry Andric template <class _RandomAccessIterator> 93fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX14 void 94fe6060f1SDimitry Andric random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) 95fe6060f1SDimitry Andric { 96fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 97fe6060f1SDimitry Andric typedef uniform_int_distribution<ptrdiff_t> _Dp; 98fe6060f1SDimitry Andric typedef typename _Dp::param_type _Pp; 99fe6060f1SDimitry Andric difference_type __d = __last - __first; 100fe6060f1SDimitry Andric if (__d > 1) 101fe6060f1SDimitry Andric { 102fe6060f1SDimitry Andric _Dp __uid; 103fe6060f1SDimitry Andric __rs_default __g = __rs_get(); 104fe6060f1SDimitry Andric for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) 105fe6060f1SDimitry Andric { 106fe6060f1SDimitry Andric difference_type __i = __uid(__g, _Pp(0, __d)); 107fe6060f1SDimitry Andric if (__i != difference_type(0)) 108fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 109fe6060f1SDimitry Andric } 110fe6060f1SDimitry Andric } 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric 113fe6060f1SDimitry Andric template <class _RandomAccessIterator, class _RandomNumberGenerator> 114fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX14 void 115fe6060f1SDimitry Andric random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, 116fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 117fe6060f1SDimitry Andric _RandomNumberGenerator&& __rand) 118fe6060f1SDimitry Andric #else 119fe6060f1SDimitry Andric _RandomNumberGenerator& __rand) 120fe6060f1SDimitry Andric #endif 121fe6060f1SDimitry Andric { 122fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 123fe6060f1SDimitry Andric difference_type __d = __last - __first; 124fe6060f1SDimitry Andric if (__d > 1) 125fe6060f1SDimitry Andric { 126fe6060f1SDimitry Andric for (--__last; __first < __last; ++__first, (void) --__d) 127fe6060f1SDimitry Andric { 128fe6060f1SDimitry Andric difference_type __i = __rand(__d); 129fe6060f1SDimitry Andric if (__i != difference_type(0)) 130fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 131fe6060f1SDimitry Andric } 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric } 134fe6060f1SDimitry Andric #endif 135fe6060f1SDimitry Andric 136fe6060f1SDimitry Andric template<class _RandomAccessIterator, class _UniformRandomNumberGenerator> 137fe6060f1SDimitry Andric void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, 138fe6060f1SDimitry Andric _UniformRandomNumberGenerator&& __g) 139fe6060f1SDimitry Andric { 140fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 141fe6060f1SDimitry Andric typedef uniform_int_distribution<ptrdiff_t> _Dp; 142fe6060f1SDimitry Andric typedef typename _Dp::param_type _Pp; 143fe6060f1SDimitry Andric difference_type __d = __last - __first; 144fe6060f1SDimitry Andric if (__d > 1) 145fe6060f1SDimitry Andric { 146fe6060f1SDimitry Andric _Dp __uid; 147fe6060f1SDimitry Andric for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) 148fe6060f1SDimitry Andric { 149fe6060f1SDimitry Andric difference_type __i = __uid(__g, _Pp(0, __d)); 150fe6060f1SDimitry Andric if (__i != difference_type(0)) 151fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 152fe6060f1SDimitry Andric } 153fe6060f1SDimitry Andric } 154fe6060f1SDimitry Andric } 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 157fe6060f1SDimitry Andric 158fe6060f1SDimitry Andric _LIBCPP_POP_MACROS 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric #endif // _LIBCPP___ALGORITHM_SHUFFLE_H 161