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> 13*81ad6265SDimitry Andric #include <__debug> 14fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 15fe6060f1SDimitry Andric #include <__random/uniform_int_distribution.h> 16fe6060f1SDimitry Andric #include <__utility/swap.h> 17fe6060f1SDimitry Andric #include <cstddef> 18fe6060f1SDimitry Andric #include <cstdint> 19fe6060f1SDimitry Andric 20fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21fe6060f1SDimitry Andric # pragma GCC system_header 22fe6060f1SDimitry Andric #endif 23fe6060f1SDimitry Andric 24fe6060f1SDimitry Andric _LIBCPP_PUSH_MACROS 25fe6060f1SDimitry Andric #include <__undef_macros> 26fe6060f1SDimitry Andric 27fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 28fe6060f1SDimitry Andric 29349cc55cSDimitry Andric class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer { 30349cc55cSDimitry Andric public: 31349cc55cSDimitry Andric __libcpp_debug_randomizer() { 32349cc55cSDimitry Andric __state = __seed(); 33349cc55cSDimitry Andric __inc = __state + 0xda3e39cb94b95bdbULL; 34349cc55cSDimitry Andric __inc = (__inc << 1) | 1; 35349cc55cSDimitry Andric } 36349cc55cSDimitry Andric typedef uint_fast32_t result_type; 37349cc55cSDimitry Andric 38349cc55cSDimitry Andric static const result_type _Min = 0; 39349cc55cSDimitry Andric static const result_type _Max = 0xFFFFFFFF; 40349cc55cSDimitry Andric 41349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type operator()() { 42349cc55cSDimitry Andric uint_fast64_t __oldstate = __state; 43349cc55cSDimitry Andric __state = __oldstate * 6364136223846793005ULL + __inc; 44349cc55cSDimitry Andric return __oldstate >> 32; 45349cc55cSDimitry Andric } 46349cc55cSDimitry Andric 47349cc55cSDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; } 48349cc55cSDimitry Andric static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; } 49349cc55cSDimitry Andric 50349cc55cSDimitry Andric private: 51349cc55cSDimitry Andric uint_fast64_t __state; 52349cc55cSDimitry Andric uint_fast64_t __inc; 53349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() { 54349cc55cSDimitry Andric #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED 55349cc55cSDimitry Andric return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED; 56349cc55cSDimitry Andric #else 57349cc55cSDimitry Andric static char __x; 58349cc55cSDimitry Andric return reinterpret_cast<uintptr_t>(&__x); 59349cc55cSDimitry Andric #endif 60349cc55cSDimitry Andric } 61349cc55cSDimitry Andric }; 62fe6060f1SDimitry Andric 63fe6060f1SDimitry Andric #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ 64fe6060f1SDimitry Andric || defined(_LIBCPP_BUILDING_LIBRARY) 65fe6060f1SDimitry Andric class _LIBCPP_TYPE_VIS __rs_default; 66fe6060f1SDimitry Andric 67fe6060f1SDimitry Andric _LIBCPP_FUNC_VIS __rs_default __rs_get(); 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric class _LIBCPP_TYPE_VIS __rs_default 70fe6060f1SDimitry Andric { 71fe6060f1SDimitry Andric static unsigned __c_; 72fe6060f1SDimitry Andric 73fe6060f1SDimitry Andric __rs_default(); 74fe6060f1SDimitry Andric public: 75fe6060f1SDimitry Andric typedef uint_fast32_t result_type; 76fe6060f1SDimitry Andric 77fe6060f1SDimitry Andric static const result_type _Min = 0; 78fe6060f1SDimitry Andric static const result_type _Max = 0xFFFFFFFF; 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric __rs_default(const __rs_default&); 81fe6060f1SDimitry Andric ~__rs_default(); 82fe6060f1SDimitry Andric 83fe6060f1SDimitry Andric result_type operator()(); 84fe6060f1SDimitry Andric 85fe6060f1SDimitry Andric static _LIBCPP_CONSTEXPR result_type min() {return _Min;} 86fe6060f1SDimitry Andric static _LIBCPP_CONSTEXPR result_type max() {return _Max;} 87fe6060f1SDimitry Andric 88fe6060f1SDimitry Andric friend _LIBCPP_FUNC_VIS __rs_default __rs_get(); 89fe6060f1SDimitry Andric }; 90fe6060f1SDimitry Andric 91fe6060f1SDimitry Andric _LIBCPP_FUNC_VIS __rs_default __rs_get(); 92fe6060f1SDimitry Andric 93fe6060f1SDimitry Andric template <class _RandomAccessIterator> 94fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX14 void 95fe6060f1SDimitry Andric random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) 96fe6060f1SDimitry Andric { 97fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 98fe6060f1SDimitry Andric typedef uniform_int_distribution<ptrdiff_t> _Dp; 99fe6060f1SDimitry Andric typedef typename _Dp::param_type _Pp; 100fe6060f1SDimitry Andric difference_type __d = __last - __first; 101fe6060f1SDimitry Andric if (__d > 1) 102fe6060f1SDimitry Andric { 103fe6060f1SDimitry Andric _Dp __uid; 104fe6060f1SDimitry Andric __rs_default __g = __rs_get(); 105fe6060f1SDimitry Andric for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) 106fe6060f1SDimitry Andric { 107fe6060f1SDimitry Andric difference_type __i = __uid(__g, _Pp(0, __d)); 108fe6060f1SDimitry Andric if (__i != difference_type(0)) 109fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 110fe6060f1SDimitry Andric } 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric } 113fe6060f1SDimitry Andric 114fe6060f1SDimitry Andric template <class _RandomAccessIterator, class _RandomNumberGenerator> 115fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX14 void 116fe6060f1SDimitry Andric random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, 117fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 118fe6060f1SDimitry Andric _RandomNumberGenerator&& __rand) 119fe6060f1SDimitry Andric #else 120fe6060f1SDimitry Andric _RandomNumberGenerator& __rand) 121fe6060f1SDimitry Andric #endif 122fe6060f1SDimitry Andric { 123fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 124fe6060f1SDimitry Andric difference_type __d = __last - __first; 125fe6060f1SDimitry Andric if (__d > 1) 126fe6060f1SDimitry Andric { 127fe6060f1SDimitry Andric for (--__last; __first < __last; ++__first, (void) --__d) 128fe6060f1SDimitry Andric { 129fe6060f1SDimitry Andric difference_type __i = __rand(__d); 130fe6060f1SDimitry Andric if (__i != difference_type(0)) 131fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric } 134fe6060f1SDimitry Andric } 135fe6060f1SDimitry Andric #endif 136fe6060f1SDimitry Andric 137fe6060f1SDimitry Andric template<class _RandomAccessIterator, class _UniformRandomNumberGenerator> 138fe6060f1SDimitry Andric void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, 139fe6060f1SDimitry Andric _UniformRandomNumberGenerator&& __g) 140fe6060f1SDimitry Andric { 141fe6060f1SDimitry Andric typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; 142fe6060f1SDimitry Andric typedef uniform_int_distribution<ptrdiff_t> _Dp; 143fe6060f1SDimitry Andric typedef typename _Dp::param_type _Pp; 144fe6060f1SDimitry Andric difference_type __d = __last - __first; 145fe6060f1SDimitry Andric if (__d > 1) 146fe6060f1SDimitry Andric { 147fe6060f1SDimitry Andric _Dp __uid; 148fe6060f1SDimitry Andric for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d) 149fe6060f1SDimitry Andric { 150fe6060f1SDimitry Andric difference_type __i = __uid(__g, _Pp(0, __d)); 151fe6060f1SDimitry Andric if (__i != difference_type(0)) 152fe6060f1SDimitry Andric swap(*__first, *(__first + __i)); 153fe6060f1SDimitry Andric } 154fe6060f1SDimitry Andric } 155fe6060f1SDimitry Andric } 156fe6060f1SDimitry Andric 157fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 158fe6060f1SDimitry Andric 159fe6060f1SDimitry Andric _LIBCPP_POP_MACROS 160fe6060f1SDimitry Andric 161fe6060f1SDimitry Andric #endif // _LIBCPP___ALGORITHM_SHUFFLE_H 162