xref: /llvm-project/libcxx/include/__cxx03/__algorithm/shuffle.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
1e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
2e78f53d1SNikolas Klauser //
3e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
5e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e78f53d1SNikolas Klauser //
7e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
8e78f53d1SNikolas Klauser 
9*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___ALGORITHM_SHUFFLE_H
10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___ALGORITHM_SHUFFLE_H
11e78f53d1SNikolas Klauser 
1273fbae83SNikolas Klauser #include <__cxx03/__algorithm/iterator_operations.h>
1373fbae83SNikolas Klauser #include <__cxx03/__config>
1473fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h>
1573fbae83SNikolas Klauser #include <__cxx03/__random/uniform_int_distribution.h>
1673fbae83SNikolas Klauser #include <__cxx03/__utility/forward.h>
1773fbae83SNikolas Klauser #include <__cxx03/__utility/move.h>
1873fbae83SNikolas Klauser #include <__cxx03/__utility/swap.h>
1973fbae83SNikolas Klauser #include <__cxx03/cstddef>
2073fbae83SNikolas Klauser #include <__cxx03/cstdint>
21e78f53d1SNikolas Klauser 
22e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23e78f53d1SNikolas Klauser #  pragma GCC system_header
24e78f53d1SNikolas Klauser #endif
25e78f53d1SNikolas Klauser 
26e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS
2773fbae83SNikolas Klauser #include <__cxx03/__undef_macros>
28e78f53d1SNikolas Klauser 
29e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD
30e78f53d1SNikolas Klauser 
31e78f53d1SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_randomizer {
32e78f53d1SNikolas Klauser public:
33e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI __libcpp_debug_randomizer() {
34e78f53d1SNikolas Klauser     __state_ = __seed();
35e78f53d1SNikolas Klauser     __inc_   = __state_ + 0xda3e39cb94b95bdbULL;
36e78f53d1SNikolas Klauser     __inc_   = (__inc_ << 1) | 1;
37e78f53d1SNikolas Klauser   }
38e78f53d1SNikolas Klauser   typedef uint_fast32_t result_type;
39e78f53d1SNikolas Klauser 
40e78f53d1SNikolas Klauser   static const result_type _Min = 0;
41e78f53d1SNikolas Klauser   static const result_type _Max = 0xFFFFFFFF;
42e78f53d1SNikolas Klauser 
43e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI result_type operator()() {
44e78f53d1SNikolas Klauser     uint_fast64_t __oldstate = __state_;
45e78f53d1SNikolas Klauser     __state_                 = __oldstate * 6364136223846793005ULL + __inc_;
46e78f53d1SNikolas Klauser     return __oldstate >> 32;
47e78f53d1SNikolas Klauser   }
48e78f53d1SNikolas Klauser 
49e78f53d1SNikolas Klauser   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; }
50e78f53d1SNikolas Klauser   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; }
51e78f53d1SNikolas Klauser 
52e78f53d1SNikolas Klauser private:
53e78f53d1SNikolas Klauser   uint_fast64_t __state_;
54e78f53d1SNikolas Klauser   uint_fast64_t __inc_;
55e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() {
56e78f53d1SNikolas Klauser #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED
57e78f53d1SNikolas Klauser     return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED;
58e78f53d1SNikolas Klauser #else
59e78f53d1SNikolas Klauser     static char __x;
60e78f53d1SNikolas Klauser     return reinterpret_cast<uintptr_t>(&__x);
61e78f53d1SNikolas Klauser #endif
62e78f53d1SNikolas Klauser   }
63e78f53d1SNikolas Klauser };
64e78f53d1SNikolas Klauser 
65e78f53d1SNikolas Klauser #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) || defined(_LIBCPP_BUILDING_LIBRARY)
66e78f53d1SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI __rs_default;
67e78f53d1SNikolas Klauser 
68e78f53d1SNikolas Klauser _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get();
69e78f53d1SNikolas Klauser 
70e78f53d1SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI __rs_default {
71e78f53d1SNikolas Klauser   static unsigned __c_;
72e78f53d1SNikolas Klauser 
73e78f53d1SNikolas Klauser   __rs_default();
74e78f53d1SNikolas Klauser 
75e78f53d1SNikolas Klauser public:
76e78f53d1SNikolas Klauser   typedef uint_fast32_t result_type;
77e78f53d1SNikolas Klauser 
78e78f53d1SNikolas Klauser   static const result_type _Min = 0;
79e78f53d1SNikolas Klauser   static const result_type _Max = 0xFFFFFFFF;
80e78f53d1SNikolas Klauser 
81e78f53d1SNikolas Klauser   __rs_default(const __rs_default&);
82e78f53d1SNikolas Klauser   ~__rs_default();
83e78f53d1SNikolas Klauser 
84e78f53d1SNikolas Klauser   result_type operator()();
85e78f53d1SNikolas Klauser 
86e78f53d1SNikolas Klauser   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; }
87e78f53d1SNikolas Klauser   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; }
88e78f53d1SNikolas Klauser 
89e78f53d1SNikolas Klauser   friend _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get();
90e78f53d1SNikolas Klauser };
91e78f53d1SNikolas Klauser 
92e78f53d1SNikolas Klauser _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get();
93e78f53d1SNikolas Klauser 
94e78f53d1SNikolas Klauser template <class _RandomAccessIterator>
95e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void
96e78f53d1SNikolas Klauser random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) {
97e78f53d1SNikolas Klauser   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
98e78f53d1SNikolas Klauser   typedef uniform_int_distribution<ptrdiff_t> _Dp;
99e78f53d1SNikolas Klauser   typedef typename _Dp::param_type _Pp;
100e78f53d1SNikolas Klauser   difference_type __d = __last - __first;
101e78f53d1SNikolas Klauser   if (__d > 1) {
102e78f53d1SNikolas Klauser     _Dp __uid;
103e78f53d1SNikolas Klauser     __rs_default __g = __rs_get();
104e78f53d1SNikolas Klauser     for (--__last, (void)--__d; __first < __last; ++__first, (void)--__d) {
105e78f53d1SNikolas Klauser       difference_type __i = __uid(__g, _Pp(0, __d));
106e78f53d1SNikolas Klauser       if (__i != difference_type(0))
107e78f53d1SNikolas Klauser         swap(*__first, *(__first + __i));
108e78f53d1SNikolas Klauser     }
109e78f53d1SNikolas Klauser   }
110e78f53d1SNikolas Klauser }
111e78f53d1SNikolas Klauser 
112e78f53d1SNikolas Klauser template <class _RandomAccessIterator, class _RandomNumberGenerator>
113e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void
114e78f53d1SNikolas Klauser random_shuffle(_RandomAccessIterator __first,
115e78f53d1SNikolas Klauser                _RandomAccessIterator __last,
116e78f53d1SNikolas Klauser #  ifndef _LIBCPP_CXX03_LANG
117e78f53d1SNikolas Klauser                _RandomNumberGenerator&& __rand)
118e78f53d1SNikolas Klauser #  else
119e78f53d1SNikolas Klauser                _RandomNumberGenerator& __rand)
120e78f53d1SNikolas Klauser #  endif
121e78f53d1SNikolas Klauser {
122e78f53d1SNikolas Klauser   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
123e78f53d1SNikolas Klauser   difference_type __d = __last - __first;
124e78f53d1SNikolas Klauser   if (__d > 1) {
125e78f53d1SNikolas Klauser     for (--__last; __first < __last; ++__first, (void)--__d) {
126e78f53d1SNikolas Klauser       difference_type __i = __rand(__d);
127e78f53d1SNikolas Klauser       if (__i != difference_type(0))
128e78f53d1SNikolas Klauser         swap(*__first, *(__first + __i));
129e78f53d1SNikolas Klauser     }
130e78f53d1SNikolas Klauser   }
131e78f53d1SNikolas Klauser }
132e78f53d1SNikolas Klauser #endif
133e78f53d1SNikolas Klauser 
134e78f53d1SNikolas Klauser template <class _AlgPolicy, class _RandomAccessIterator, class _Sentinel, class _UniformRandomNumberGenerator>
135e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
136e78f53d1SNikolas Klauser __shuffle(_RandomAccessIterator __first, _Sentinel __last_sentinel, _UniformRandomNumberGenerator&& __g) {
137e78f53d1SNikolas Klauser   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
138e78f53d1SNikolas Klauser   typedef uniform_int_distribution<ptrdiff_t> _Dp;
139e78f53d1SNikolas Klauser   typedef typename _Dp::param_type _Pp;
140e78f53d1SNikolas Klauser 
141e78f53d1SNikolas Klauser   auto __original_last = _IterOps<_AlgPolicy>::next(__first, __last_sentinel);
142e78f53d1SNikolas Klauser   auto __last          = __original_last;
143e78f53d1SNikolas Klauser   difference_type __d  = __last - __first;
144e78f53d1SNikolas Klauser   if (__d > 1) {
145e78f53d1SNikolas Klauser     _Dp __uid;
146e78f53d1SNikolas Klauser     for (--__last, (void)--__d; __first < __last; ++__first, (void)--__d) {
147e78f53d1SNikolas Klauser       difference_type __i = __uid(__g, _Pp(0, __d));
148e78f53d1SNikolas Klauser       if (__i != difference_type(0))
149e78f53d1SNikolas Klauser         _IterOps<_AlgPolicy>::iter_swap(__first, __first + __i);
150e78f53d1SNikolas Klauser     }
151e78f53d1SNikolas Klauser   }
152e78f53d1SNikolas Klauser 
153e78f53d1SNikolas Klauser   return __original_last;
154e78f53d1SNikolas Klauser }
155e78f53d1SNikolas Klauser 
156e78f53d1SNikolas Klauser template <class _RandomAccessIterator, class _UniformRandomNumberGenerator>
157e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void
158e78f53d1SNikolas Klauser shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _UniformRandomNumberGenerator&& __g) {
159e78f53d1SNikolas Klauser   (void)std::__shuffle<_ClassicAlgPolicy>(
160e78f53d1SNikolas Klauser       std::move(__first), std::move(__last), std::forward<_UniformRandomNumberGenerator>(__g));
161e78f53d1SNikolas Klauser }
162e78f53d1SNikolas Klauser 
163e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD
164e78f53d1SNikolas Klauser 
165e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS
166e78f53d1SNikolas Klauser 
167*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___ALGORITHM_SHUFFLE_H
168