1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___ALGORITHM_SHUFFLE_H
10 #define _LIBCPP___ALGORITHM_SHUFFLE_H
12 #include <__algorithm/iterator_operations.h>
14 #include <__cstddef/ptrdiff_t.h>
15 #include <__iterator/iterator_traits.h>
16 #include <__random/uniform_int_distribution.h>
17 #include <__utility/forward.h>
18 #include <__utility/move.h>
19 #include <__utility/swap.h>
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 # pragma GCC system_header
27 #include <__undef_macros>
29 _LIBCPP_BEGIN_NAMESPACE_STD
31 class _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_randomizer
{
33 _LIBCPP_HIDE_FROM_ABI
__libcpp_debug_randomizer() {
35 __inc_
= __state_
+ 0xda3e39cb94b95bdbULL
;
36 __inc_
= (__inc_
<< 1) | 1;
38 typedef uint_fast32_t result_type
;
40 static const result_type _Min
= 0;
41 static const result_type _Max
= 0xFFFFFFFF;
43 _LIBCPP_HIDE_FROM_ABI result_type
operator()() {
44 uint_fast64_t __oldstate
= __state_
;
45 __state_
= __oldstate
* 6364136223846793005ULL + __inc_
;
46 return __oldstate
>> 32;
49 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type
min() { return _Min
; }
50 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type
max() { return _Max
; }
53 uint_fast64_t __state_
;
55 _LIBCPP_HIDE_FROM_ABI
static uint_fast64_t __seed() {
56 #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED
57 return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED
;
60 return reinterpret_cast<uintptr_t>(&__x
);
65 #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) || defined(_LIBCPP_BUILDING_LIBRARY)
66 class _LIBCPP_EXPORTED_FROM_ABI __rs_default
;
68 _LIBCPP_EXPORTED_FROM_ABI __rs_default
__rs_get();
70 class _LIBCPP_EXPORTED_FROM_ABI __rs_default
{
76 typedef uint_fast32_t result_type
;
78 static const result_type _Min
= 0;
79 static const result_type _Max
= 0xFFFFFFFF;
81 __rs_default(const __rs_default
&);
84 result_type
operator()();
86 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type
min() { return _Min
; }
87 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type
max() { return _Max
; }
89 friend _LIBCPP_EXPORTED_FROM_ABI __rs_default
__rs_get();
92 _LIBCPP_EXPORTED_FROM_ABI __rs_default
__rs_get();
94 template <class _RandomAccessIterator
>
95 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14
void
96 random_shuffle(_RandomAccessIterator __first
, _RandomAccessIterator __last
) {
97 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type difference_type
;
98 typedef uniform_int_distribution
<ptrdiff_t> _Dp
;
99 typedef typename
_Dp::param_type _Pp
;
100 difference_type __d
= __last
- __first
;
103 __rs_default __g
= __rs_get();
104 for (--__last
, (void)--__d
; __first
< __last
; ++__first
, (void)--__d
) {
105 difference_type __i
= __uid(__g
, _Pp(0, __d
));
106 if (__i
!= difference_type(0))
107 swap(*__first
, *(__first
+ __i
));
112 template <class _RandomAccessIterator
, class _RandomNumberGenerator
>
113 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14
void
114 random_shuffle(_RandomAccessIterator __first
,
115 _RandomAccessIterator __last
,
116 # ifndef _LIBCPP_CXX03_LANG
117 _RandomNumberGenerator
&& __rand
)
119 _RandomNumberGenerator
& __rand
)
122 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type difference_type
;
123 difference_type __d
= __last
- __first
;
125 for (--__last
; __first
< __last
; ++__first
, (void)--__d
) {
126 difference_type __i
= __rand(__d
);
127 if (__i
!= difference_type(0))
128 swap(*__first
, *(__first
+ __i
));
134 template <class _AlgPolicy
, class _RandomAccessIterator
, class _Sentinel
, class _UniformRandomNumberGenerator
>
135 _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
136 __shuffle(_RandomAccessIterator __first
, _Sentinel __last_sentinel
, _UniformRandomNumberGenerator
&& __g
) {
137 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type difference_type
;
138 typedef uniform_int_distribution
<ptrdiff_t> _Dp
;
139 typedef typename
_Dp::param_type _Pp
;
141 auto __original_last
= _IterOps
<_AlgPolicy
>::next(__first
, __last_sentinel
);
142 auto __last
= __original_last
;
143 difference_type __d
= __last
- __first
;
146 for (--__last
, (void)--__d
; __first
< __last
; ++__first
, (void)--__d
) {
147 difference_type __i
= __uid(__g
, _Pp(0, __d
));
148 if (__i
!= difference_type(0))
149 _IterOps
<_AlgPolicy
>::iter_swap(__first
, __first
+ __i
);
153 return __original_last
;
156 template <class _RandomAccessIterator
, class _UniformRandomNumberGenerator
>
157 _LIBCPP_HIDE_FROM_ABI
void
158 shuffle(_RandomAccessIterator __first
, _RandomAccessIterator __last
, _UniformRandomNumberGenerator
&& __g
) {
159 (void)std::__shuffle
<_ClassicAlgPolicy
>(
160 std::move(__first
), std::move(__last
), std::forward
<_UniformRandomNumberGenerator
>(__g
));
163 _LIBCPP_END_NAMESPACE_STD
167 #endif // _LIBCPP___ALGORITHM_SHUFFLE_H