random_shuffle.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright Neil Groves 2009. Use, modification and
  2. // distribution is subject to the Boost Software License, Version
  3. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. //
  7. // For more information, see http://www.boost.org/libs/range/
  8. //
  9. #ifndef BOOST_RANGE_ALGORITHM_RANDOM_SHUFFLE_HPP_INCLUDED
  10. #define BOOST_RANGE_ALGORITHM_RANDOM_SHUFFLE_HPP_INCLUDED
  11. #include <boost/concept_check.hpp>
  12. #include <boost/range/begin.hpp>
  13. #include <boost/range/end.hpp>
  14. #include <boost/range/concepts.hpp>
  15. #include <algorithm>
  16. #ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
  17. #include <cstdlib>
  18. #endif
  19. namespace boost
  20. {
  21. namespace range
  22. {
  23. namespace detail
  24. {
  25. #ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
  26. // wrap std::rand as UniformRandomBitGenerator
  27. struct wrap_rand
  28. {
  29. typedef unsigned int result_type;
  30. static BOOST_CONSTEXPR result_type (min)()
  31. {
  32. return 0;
  33. }
  34. static BOOST_CONSTEXPR result_type (max)()
  35. {
  36. return RAND_MAX;
  37. }
  38. result_type operator()()
  39. {
  40. return std::rand();
  41. }
  42. };
  43. template< class RandomIt >
  44. inline void random_shuffle(RandomIt first, RandomIt last)
  45. {
  46. std::shuffle(first, last, wrap_rand());
  47. }
  48. // wrap Generator as UniformRandomBitGenerator
  49. template< class Generator >
  50. struct wrap_generator
  51. {
  52. typedef unsigned int result_type;
  53. static const int max_arg = ((0u - 1u) >> 2) + 1;
  54. Generator& g;
  55. wrap_generator(Generator& gen) : g(gen) {}
  56. static BOOST_CONSTEXPR result_type (min)()
  57. {
  58. return 0;
  59. }
  60. static BOOST_CONSTEXPR result_type (max)()
  61. {
  62. return max_arg - 1;
  63. }
  64. result_type operator()()
  65. {
  66. return static_cast<result_type>(g(max_arg));
  67. }
  68. };
  69. template< class RandomIt, class Generator >
  70. inline void random_shuffle(RandomIt first, RandomIt last, Generator& gen)
  71. {
  72. std::shuffle(first, last, wrap_generator< Generator >(gen));
  73. }
  74. #else
  75. using std::random_shuffle;
  76. #endif
  77. } // namespace detail
  78. /// \brief template function random_shuffle
  79. ///
  80. /// range-based version of the random_shuffle std algorithm
  81. ///
  82. /// \pre RandomAccessRange is a model of the RandomAccessRangeConcept
  83. /// \pre Generator is a model of the UnaryFunctionConcept
  84. template<class RandomAccessRange>
  85. inline RandomAccessRange& random_shuffle(RandomAccessRange& rng)
  86. {
  87. BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept<RandomAccessRange> ));
  88. detail::random_shuffle(boost::begin(rng), boost::end(rng));
  89. return rng;
  90. }
  91. /// \overload
  92. template<class RandomAccessRange>
  93. inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng)
  94. {
  95. BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept<const RandomAccessRange> ));
  96. detail::random_shuffle(boost::begin(rng), boost::end(rng));
  97. return rng;
  98. }
  99. /// \overload
  100. template<class RandomAccessRange, class Generator>
  101. inline RandomAccessRange& random_shuffle(RandomAccessRange& rng, Generator& gen)
  102. {
  103. BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept<RandomAccessRange> ));
  104. detail::random_shuffle(boost::begin(rng), boost::end(rng), gen);
  105. return rng;
  106. }
  107. /// \overload
  108. template<class RandomAccessRange, class Generator>
  109. inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng, Generator& gen)
  110. {
  111. BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept<const RandomAccessRange> ));
  112. detail::random_shuffle(boost::begin(rng), boost::end(rng), gen);
  113. return rng;
  114. }
  115. } // namespace range
  116. using range::random_shuffle;
  117. } // namespace boost
  118. #endif // include guard