xref: /openbsd-src/gnu/llvm/libcxx/include/__algorithm/shuffle.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
176d0caaeSpatrick //===----------------------------------------------------------------------===//
276d0caaeSpatrick //
376d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
476d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
576d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
676d0caaeSpatrick //
776d0caaeSpatrick //===----------------------------------------------------------------------===//
876d0caaeSpatrick 
976d0caaeSpatrick #ifndef _LIBCPP___ALGORITHM_SHUFFLE_H
1076d0caaeSpatrick #define _LIBCPP___ALGORITHM_SHUFFLE_H
1176d0caaeSpatrick 
12*4bdff4beSrobert #include <__algorithm/iterator_operations.h>
1376d0caaeSpatrick #include <__config>
14*4bdff4beSrobert #include <__debug>
1576d0caaeSpatrick #include <__iterator/iterator_traits.h>
1676d0caaeSpatrick #include <__random/uniform_int_distribution.h>
17*4bdff4beSrobert #include <__utility/forward.h>
18*4bdff4beSrobert #include <__utility/move.h>
1976d0caaeSpatrick #include <__utility/swap.h>
2076d0caaeSpatrick #include <cstddef>
2176d0caaeSpatrick #include <cstdint>
2276d0caaeSpatrick 
2376d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2476d0caaeSpatrick #  pragma GCC system_header
2576d0caaeSpatrick #endif
2676d0caaeSpatrick 
2776d0caaeSpatrick _LIBCPP_PUSH_MACROS
2876d0caaeSpatrick #include <__undef_macros>
2976d0caaeSpatrick 
3076d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD
3176d0caaeSpatrick 
32*4bdff4beSrobert class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer {
33*4bdff4beSrobert public:
__libcpp_debug_randomizer()34*4bdff4beSrobert   __libcpp_debug_randomizer() {
35*4bdff4beSrobert     __state_ = __seed();
36*4bdff4beSrobert     __inc_ = __state_ + 0xda3e39cb94b95bdbULL;
37*4bdff4beSrobert     __inc_ = (__inc_ << 1) | 1;
38*4bdff4beSrobert   }
39*4bdff4beSrobert   typedef uint_fast32_t result_type;
40*4bdff4beSrobert 
41*4bdff4beSrobert   static const result_type _Min = 0;
42*4bdff4beSrobert   static const result_type _Max = 0xFFFFFFFF;
43*4bdff4beSrobert 
operator()44*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI result_type operator()() {
45*4bdff4beSrobert     uint_fast64_t __oldstate = __state_;
46*4bdff4beSrobert     __state_ = __oldstate * 6364136223846793005ULL + __inc_;
47*4bdff4beSrobert     return __oldstate >> 32;
48*4bdff4beSrobert   }
49*4bdff4beSrobert 
min()50*4bdff4beSrobert   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() { return _Min; }
max()51*4bdff4beSrobert   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; }
52*4bdff4beSrobert 
53*4bdff4beSrobert private:
54*4bdff4beSrobert   uint_fast64_t __state_;
55*4bdff4beSrobert   uint_fast64_t __inc_;
__seed()56*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() {
57*4bdff4beSrobert #ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED
58*4bdff4beSrobert     return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED;
59*4bdff4beSrobert #else
60*4bdff4beSrobert     static char __x;
61*4bdff4beSrobert     return reinterpret_cast<uintptr_t>(&__x);
62*4bdff4beSrobert #endif
63*4bdff4beSrobert   }
64*4bdff4beSrobert };
6576d0caaeSpatrick 
6676d0caaeSpatrick #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \
6776d0caaeSpatrick   || defined(_LIBCPP_BUILDING_LIBRARY)
6876d0caaeSpatrick class _LIBCPP_TYPE_VIS __rs_default;
6976d0caaeSpatrick 
7076d0caaeSpatrick _LIBCPP_FUNC_VIS __rs_default __rs_get();
7176d0caaeSpatrick 
7276d0caaeSpatrick class _LIBCPP_TYPE_VIS __rs_default
7376d0caaeSpatrick {
7476d0caaeSpatrick     static unsigned __c_;
7576d0caaeSpatrick 
7676d0caaeSpatrick     __rs_default();
7776d0caaeSpatrick public:
7876d0caaeSpatrick     typedef uint_fast32_t result_type;
7976d0caaeSpatrick 
8076d0caaeSpatrick     static const result_type _Min = 0;
8176d0caaeSpatrick     static const result_type _Max = 0xFFFFFFFF;
8276d0caaeSpatrick 
8376d0caaeSpatrick     __rs_default(const __rs_default&);
8476d0caaeSpatrick     ~__rs_default();
8576d0caaeSpatrick 
8676d0caaeSpatrick     result_type operator()();
8776d0caaeSpatrick 
min()8876d0caaeSpatrick     static _LIBCPP_CONSTEXPR result_type min() {return _Min;}
max()8976d0caaeSpatrick     static _LIBCPP_CONSTEXPR result_type max() {return _Max;}
9076d0caaeSpatrick 
9176d0caaeSpatrick     friend _LIBCPP_FUNC_VIS __rs_default __rs_get();
9276d0caaeSpatrick };
9376d0caaeSpatrick 
9476d0caaeSpatrick _LIBCPP_FUNC_VIS __rs_default __rs_get();
9576d0caaeSpatrick 
9676d0caaeSpatrick template <class _RandomAccessIterator>
97*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void
random_shuffle(_RandomAccessIterator __first,_RandomAccessIterator __last)9876d0caaeSpatrick random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
9976d0caaeSpatrick {
10076d0caaeSpatrick     typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
10176d0caaeSpatrick     typedef uniform_int_distribution<ptrdiff_t> _Dp;
10276d0caaeSpatrick     typedef typename _Dp::param_type _Pp;
10376d0caaeSpatrick     difference_type __d = __last - __first;
10476d0caaeSpatrick     if (__d > 1)
10576d0caaeSpatrick     {
10676d0caaeSpatrick         _Dp __uid;
10776d0caaeSpatrick         __rs_default __g = __rs_get();
10876d0caaeSpatrick         for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d)
10976d0caaeSpatrick         {
11076d0caaeSpatrick             difference_type __i = __uid(__g, _Pp(0, __d));
11176d0caaeSpatrick             if (__i != difference_type(0))
11276d0caaeSpatrick                 swap(*__first, *(__first + __i));
11376d0caaeSpatrick         }
11476d0caaeSpatrick     }
11576d0caaeSpatrick }
11676d0caaeSpatrick 
11776d0caaeSpatrick template <class _RandomAccessIterator, class _RandomNumberGenerator>
118*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void
random_shuffle(_RandomAccessIterator __first,_RandomAccessIterator __last,_RandomNumberGenerator && __rand)11976d0caaeSpatrick random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
12076d0caaeSpatrick #ifndef _LIBCPP_CXX03_LANG
12176d0caaeSpatrick                _RandomNumberGenerator&& __rand)
12276d0caaeSpatrick #else
12376d0caaeSpatrick                _RandomNumberGenerator& __rand)
12476d0caaeSpatrick #endif
12576d0caaeSpatrick {
12676d0caaeSpatrick     typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
12776d0caaeSpatrick     difference_type __d = __last - __first;
12876d0caaeSpatrick     if (__d > 1)
12976d0caaeSpatrick     {
13076d0caaeSpatrick         for (--__last; __first < __last; ++__first, (void) --__d)
13176d0caaeSpatrick         {
13276d0caaeSpatrick             difference_type __i = __rand(__d);
13376d0caaeSpatrick             if (__i != difference_type(0))
13476d0caaeSpatrick               swap(*__first, *(__first + __i));
13576d0caaeSpatrick         }
13676d0caaeSpatrick     }
13776d0caaeSpatrick }
13876d0caaeSpatrick #endif
13976d0caaeSpatrick 
140*4bdff4beSrobert template <class _AlgPolicy, class _RandomAccessIterator, class _Sentinel, class _UniformRandomNumberGenerator>
__shuffle(_RandomAccessIterator __first,_Sentinel __last_sentinel,_UniformRandomNumberGenerator && __g)141*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator __shuffle(
142*4bdff4beSrobert     _RandomAccessIterator __first, _Sentinel __last_sentinel, _UniformRandomNumberGenerator&& __g) {
14376d0caaeSpatrick     typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
14476d0caaeSpatrick     typedef uniform_int_distribution<ptrdiff_t> _Dp;
14576d0caaeSpatrick     typedef typename _Dp::param_type _Pp;
146*4bdff4beSrobert 
147*4bdff4beSrobert     auto __original_last = _IterOps<_AlgPolicy>::next(__first, __last_sentinel);
148*4bdff4beSrobert     auto __last = __original_last;
14976d0caaeSpatrick     difference_type __d = __last - __first;
15076d0caaeSpatrick     if (__d > 1)
15176d0caaeSpatrick     {
15276d0caaeSpatrick         _Dp __uid;
15376d0caaeSpatrick         for (--__last, (void) --__d; __first < __last; ++__first, (void) --__d)
15476d0caaeSpatrick         {
15576d0caaeSpatrick             difference_type __i = __uid(__g, _Pp(0, __d));
15676d0caaeSpatrick             if (__i != difference_type(0))
157*4bdff4beSrobert                 _IterOps<_AlgPolicy>::iter_swap(__first, __first + __i);
15876d0caaeSpatrick         }
15976d0caaeSpatrick     }
160*4bdff4beSrobert 
161*4bdff4beSrobert     return __original_last;
162*4bdff4beSrobert }
163*4bdff4beSrobert 
164*4bdff4beSrobert template <class _RandomAccessIterator, class _UniformRandomNumberGenerator>
165*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI void
shuffle(_RandomAccessIterator __first,_RandomAccessIterator __last,_UniformRandomNumberGenerator && __g)166*4bdff4beSrobert shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _UniformRandomNumberGenerator&& __g) {
167*4bdff4beSrobert   (void)std::__shuffle<_ClassicAlgPolicy>(
168*4bdff4beSrobert       std::move(__first), std::move(__last), std::forward<_UniformRandomNumberGenerator>(__g));
16976d0caaeSpatrick }
17076d0caaeSpatrick 
17176d0caaeSpatrick _LIBCPP_END_NAMESPACE_STD
17276d0caaeSpatrick 
17376d0caaeSpatrick _LIBCPP_POP_MACROS
17476d0caaeSpatrick 
17576d0caaeSpatrick #endif // _LIBCPP___ALGORITHM_SHUFFLE_H
176