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 <__iterator/iterator_traits.h>
15 #include <__random/uniform_int_distribution.h>
16 #include <__utility/forward.h>
17 #include <__utility/move.h>
18 #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) \
66 || defined(_LIBCPP_BUILDING_LIBRARY)
67 class _LIBCPP_EXPORTED_FROM_ABI __rs_default
;
69 _LIBCPP_EXPORTED_FROM_ABI __rs_default
__rs_get();
71 class _LIBCPP_EXPORTED_FROM_ABI __rs_default
77 typedef uint_fast32_t result_type
;
79 static const result_type _Min
= 0;
80 static const result_type _Max
= 0xFFFFFFFF;
82 __rs_default(const __rs_default
&);
85 result_type
operator()();
87 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type
min() {return _Min
;}
88 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type
max() {return _Max
;}
90 friend _LIBCPP_EXPORTED_FROM_ABI __rs_default
__rs_get();
93 _LIBCPP_EXPORTED_FROM_ABI __rs_default
__rs_get();
95 template <class _RandomAccessIterator
>
96 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14
void
97 random_shuffle(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
99 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type difference_type
;
100 typedef uniform_int_distribution
<ptrdiff_t> _Dp
;
101 typedef typename
_Dp::param_type _Pp
;
102 difference_type __d
= __last
- __first
;
106 __rs_default __g
= __rs_get();
107 for (--__last
, (void) --__d
; __first
< __last
; ++__first
, (void) --__d
)
109 difference_type __i
= __uid(__g
, _Pp(0, __d
));
110 if (__i
!= difference_type(0))
111 swap(*__first
, *(__first
+ __i
));
116 template <class _RandomAccessIterator
, class _RandomNumberGenerator
>
117 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14
void
118 random_shuffle(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
119 #ifndef _LIBCPP_CXX03_LANG
120 _RandomNumberGenerator
&& __rand
)
122 _RandomNumberGenerator
& __rand
)
125 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type difference_type
;
126 difference_type __d
= __last
- __first
;
129 for (--__last
; __first
< __last
; ++__first
, (void) --__d
)
131 difference_type __i
= __rand(__d
);
132 if (__i
!= difference_type(0))
133 swap(*__first
, *(__first
+ __i
));
139 template <class _AlgPolicy
, class _RandomAccessIterator
, class _Sentinel
, class _UniformRandomNumberGenerator
>
140 _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
__shuffle(
141 _RandomAccessIterator __first
, _Sentinel __last_sentinel
, _UniformRandomNumberGenerator
&& __g
) {
142 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type difference_type
;
143 typedef uniform_int_distribution
<ptrdiff_t> _Dp
;
144 typedef typename
_Dp::param_type _Pp
;
146 auto __original_last
= _IterOps
<_AlgPolicy
>::next(__first
, __last_sentinel
);
147 auto __last
= __original_last
;
148 difference_type __d
= __last
- __first
;
152 for (--__last
, (void) --__d
; __first
< __last
; ++__first
, (void) --__d
)
154 difference_type __i
= __uid(__g
, _Pp(0, __d
));
155 if (__i
!= difference_type(0))
156 _IterOps
<_AlgPolicy
>::iter_swap(__first
, __first
+ __i
);
160 return __original_last
;
163 template <class _RandomAccessIterator
, class _UniformRandomNumberGenerator
>
164 _LIBCPP_HIDE_FROM_ABI
void
165 shuffle(_RandomAccessIterator __first
, _RandomAccessIterator __last
, _UniformRandomNumberGenerator
&& __g
) {
166 (void)std::__shuffle
<_ClassicAlgPolicy
>(
167 std::move(__first
), std::move(__last
), std::forward
<_UniformRandomNumberGenerator
>(__g
));
170 _LIBCPP_END_NAMESPACE_STD
174 #endif // _LIBCPP___ALGORITHM_SHUFFLE_H