File indexing completed on 2025-01-18 09:51:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_RANDOM_SHUFFLE_ORDER_HPP
0016 #define BOOST_RANDOM_SHUFFLE_ORDER_HPP
0017
0018 #include <iostream>
0019 #include <algorithm> // std::copy
0020 #include <cassert>
0021 #include <boost/config.hpp>
0022 #include <boost/limits.hpp>
0023 #include <boost/static_assert.hpp>
0024 #include <boost/cstdint.hpp>
0025 #include <boost/random/detail/operators.hpp>
0026 #include <boost/random/detail/seed.hpp>
0027 #include <boost/random/detail/signed_unsigned_tools.hpp>
0028 #include <boost/random/linear_congruential.hpp>
0029
0030 #include <boost/random/detail/disable_warnings.hpp>
0031
0032 namespace boost {
0033 namespace random {
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template<class UniformRandomNumberGenerator, std::size_t k>
0059 class shuffle_order_engine
0060 {
0061 public:
0062 typedef UniformRandomNumberGenerator base_type;
0063 typedef typename base_type::result_type result_type;
0064
0065 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
0066 BOOST_STATIC_CONSTANT(std::size_t, buffer_size = k);
0067 BOOST_STATIC_CONSTANT(std::size_t, table_size = k);
0068
0069 BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
0070 BOOST_STATIC_ASSERT(k > 0);
0071
0072
0073
0074
0075
0076
0077
0078 shuffle_order_engine() : _rng() { init(); }
0079
0080
0081
0082
0083
0084
0085 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(shuffle_order_engine,
0086 result_type, s)
0087 { _rng.seed(s); init(); }
0088 BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(shuffle_order_engine, SeedSeq, seq)
0089 { _rng.seed(seq); init(); }
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 explicit shuffle_order_engine(const base_type & rng) : _rng(rng) { init(); }
0100
0101 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0102 explicit shuffle_order_engine(base_type&& rng) : _rng(rng) { init(); }
0103 #endif
0104
0105 template<class It> shuffle_order_engine(It& first, It last)
0106 : _rng(first, last) { init(); }
0107 void seed() { _rng.seed(); init(); }
0108
0109
0110
0111
0112
0113
0114 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(shuffle_order_engine,
0115 result_type, seed_arg)
0116 { _rng.seed(seed_arg); init(); }
0117
0118
0119
0120
0121
0122
0123 BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(shuffle_order_engine, SeedSeq, seq)
0124 { _rng.seed(seq); init(); }
0125 template<class It> void seed(It& first, It last)
0126 { _rng.seed(first, last); init(); }
0127
0128 const base_type& base() const { return _rng; }
0129
0130 result_type operator()() {
0131
0132
0133 typedef typename boost::random::traits::make_unsigned<result_type>::type base_unsigned;
0134 const base_unsigned brange =
0135 detail::subtract<result_type>()((max)(), (min)());
0136 const base_unsigned off =
0137 detail::subtract<result_type>()(y, (min)());
0138
0139 base_unsigned j;
0140 if(k == 1) {
0141 j = 0;
0142 } else if(brange < (std::numeric_limits<base_unsigned>::max)() / k) {
0143
0144
0145 j = k * off / (brange + 1);
0146 } else if(brange < (std::numeric_limits<uintmax_t>::max)() / k) {
0147
0148 j = static_cast<base_unsigned>(
0149 static_cast<uintmax_t>(off) * k /
0150 (static_cast<uintmax_t>(brange) + 1));
0151 } else {
0152 boost::uintmax_t divisor =
0153 static_cast<boost::uintmax_t>(brange) + 1;
0154 j = static_cast<base_unsigned>(detail::muldiv(off, k, divisor));
0155 }
0156
0157 y = v[j];
0158 v[j] = _rng();
0159 return y;
0160 }
0161
0162
0163 void discard(boost::uintmax_t z)
0164 {
0165 for(boost::uintmax_t j = 0; j < z; ++j) {
0166 (*this)();
0167 }
0168 }
0169
0170
0171 template<class Iter>
0172 void generate(Iter first, Iter last)
0173 { detail::generate_from_int(*this, first, last); }
0174
0175
0176 static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0177 { return (base_type::min)(); }
0178
0179 static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0180 { return (base_type::max)(); }
0181
0182
0183 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, shuffle_order_engine, s)
0184 {
0185 os << s._rng;
0186 for(std::size_t i = 0; i < k; ++i)
0187 os << ' ' << s.v[i];
0188 os << ' ' << s.y;
0189 return os;
0190 }
0191
0192
0193 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, shuffle_order_engine, s)
0194 {
0195 is >> s._rng;
0196 for(std::size_t i = 0; i < k; ++i)
0197 is >> std::ws >> s.v[i];
0198 is >> std::ws >> s.y;
0199 return is;
0200 }
0201
0202
0203 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(shuffle_order_engine, x, y)
0204 { return x._rng == y._rng && x.y == y.y && std::equal(x.v, x.v+k, y.v); }
0205
0206 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(shuffle_order_engine)
0207
0208 private:
0209
0210
0211
0212 void init()
0213 {
0214
0215 for(result_type * p = v; p != v+k; ++p)
0216 *p = _rng();
0217 y = _rng();
0218 }
0219
0220
0221
0222 base_type _rng;
0223 result_type v[k];
0224 result_type y;
0225 };
0226
0227 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
0228
0229 template<class URNG, std::size_t k>
0230 const bool shuffle_order_engine<URNG, k>::has_fixed_range;
0231 template<class URNG, std::size_t k>
0232 const std::size_t shuffle_order_engine<URNG, k>::table_size;
0233 template<class URNG, std::size_t k>
0234 const std::size_t shuffle_order_engine<URNG, k>::buffer_size;
0235 #endif
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 typedef shuffle_order_engine<
0247 linear_congruential_engine<uint32_t, 1366, 150889, 714025>,
0248 97> kreutzer1986;
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;
0260
0261 }
0262
0263 using random::kreutzer1986;
0264
0265 }
0266
0267 #include <boost/random/detail/enable_warnings.hpp>
0268
0269 #endif