11 #ifndef TLX_ALGORITHM_RANDOM_BIPARTITION_SHUFFLE_HEADER 12 #define TLX_ALGORITHM_RANDOM_BIPARTITION_SHUFFLE_HEADER 43 template <
typename RandomAccessIt,
typename RandomBits>
45 size_t size_left_partition, RandomBits& urng) {
46 const size_t size = std::distance(begin, end);
47 assert(size_left_partition <= size);
50 const size_t size_right_partition = size - size_left_partition;
51 if (!size_left_partition || !size_right_partition)
return;
55 auto two_random_variates =
56 [&urng](
size_t a,
size_t b) {
57 auto x = std::uniform_int_distribution<size_t>{ 0, (a * b) - 1 } (urng);
58 return std::make_pair(x / b, x % b);
65 if (size_left_partition < size_right_partition) {
70 for (
size_t i = 1; i < size_left_partition; i += 2) {
71 auto rand = two_random_variates(size - i + 1, size - i);
72 swap(*it++, *std::next(begin, size - 1 - rand.first));
73 swap(*it++, *std::next(begin, size - 1 - rand.second));
78 if (size_left_partition % 2) {
79 auto x = std::uniform_int_distribution<size_t>{ size_left_partition - 1, size - 1 } (urng);
80 swap(*it, *std::next(begin, x));
85 auto it = std::next(begin, size - 1);
87 for (
size_t i = size - 2; i >= size_left_partition; i -= 2) {
88 auto rand = two_random_variates(i + 2, i + 1);
89 swap(*it--, *std::next(begin, rand.first));
90 swap(*it--, *std::next(begin, rand.second));
93 if (size_right_partition % 2) {
94 auto x = std::uniform_int_distribution<size_t>{ 0, size_left_partition } (urng);
95 swap(*it--, *std::next(begin, x));
104 #endif // !TLX_ALGORITHM_RANDOM_BIPARTITION_SHUFFLE_HEADER
void random_bipartition_shuffle(RandomAccessIt begin, RandomAccessIt end, size_t size_left_partition, RandomBits &urng)
Similar to std::shuffle, but only generates a random bi-partition.
void swap(CountingPtr< A, D > &a1, CountingPtr< A, D > &a2) noexcept
swap enclosed object with another counting pointer (no reference counts need change) ...