File indexing completed on 2025-01-18 09:51:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_RANDOM_ADDITIVE_COMBINE_HPP
0017 #define BOOST_RANDOM_ADDITIVE_COMBINE_HPP
0018
0019 #include <istream>
0020 #include <iosfwd>
0021 #include <algorithm> // for std::min and std::max
0022 #include <boost/config.hpp>
0023 #include <boost/cstdint.hpp>
0024 #include <boost/random/detail/config.hpp>
0025 #include <boost/random/detail/operators.hpp>
0026 #include <boost/random/detail/seed.hpp>
0027 #include <boost/random/linear_congruential.hpp>
0028
0029 namespace boost {
0030 namespace random {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 template<class MLCG1, class MLCG2>
0050 class additive_combine_engine
0051 {
0052 public:
0053 typedef MLCG1 first_base;
0054 typedef MLCG2 second_base;
0055 typedef typename MLCG1::result_type result_type;
0056
0057
0058 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
0059
0060
0061
0062 static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0063 { return 1; }
0064
0065
0066
0067 static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0068 { return MLCG1::modulus-1; }
0069
0070
0071
0072
0073
0074 additive_combine_engine() : _mlcg1(), _mlcg2() { }
0075
0076
0077
0078
0079 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(additive_combine_engine,
0080 result_type, seed_arg)
0081 {
0082 _mlcg1.seed(seed_arg);
0083 _mlcg2.seed(seed_arg);
0084 }
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(additive_combine_engine,
0098 SeedSeq, seq)
0099 {
0100 _mlcg1.seed(seq);
0101 _mlcg2.seed(seq);
0102 }
0103
0104
0105
0106
0107
0108 additive_combine_engine(typename MLCG1::result_type seed1,
0109 typename MLCG2::result_type seed2)
0110 : _mlcg1(seed1), _mlcg2(seed2) { }
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 template<class It> additive_combine_engine(It& first, It last)
0122 : _mlcg1(first, last), _mlcg2(first, last) { }
0123
0124
0125
0126
0127
0128 void seed()
0129 {
0130 _mlcg1.seed();
0131 _mlcg2.seed();
0132 }
0133
0134
0135
0136
0137
0138 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(additive_combine_engine,
0139 result_type, seed_arg)
0140 {
0141 _mlcg1.seed(seed_arg);
0142 _mlcg2.seed(seed_arg);
0143 }
0144
0145
0146
0147
0148
0149
0150
0151 BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(additive_combine_engine,
0152 SeedSeq, seq)
0153 {
0154 _mlcg1.seed(seq);
0155 _mlcg2.seed(seq);
0156 }
0157
0158
0159
0160
0161
0162 void seed(typename MLCG1::result_type seed1,
0163 typename MLCG2::result_type seed2)
0164 {
0165 _mlcg1.seed(seed1);
0166 _mlcg2.seed(seed2);
0167 }
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179 template<class It> void seed(It& first, It last)
0180 {
0181 _mlcg1.seed(first, last);
0182 _mlcg2.seed(first, last);
0183 }
0184
0185
0186 result_type operator()() {
0187 result_type val1 = _mlcg1();
0188 result_type val2 = _mlcg2();
0189 if(val2 < val1) return val1 - val2;
0190 else return val1 - val2 + MLCG1::modulus - 1;
0191 }
0192
0193
0194 template<class Iter>
0195 void generate(Iter first, Iter last)
0196 { detail::generate_from_int(*this, first, last); }
0197
0198
0199 void discard(boost::uintmax_t z)
0200 {
0201 _mlcg1.discard(z);
0202 _mlcg2.discard(z);
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, additive_combine_engine, r)
0213 { os << r._mlcg1 << ' ' << r._mlcg2; return os; }
0214
0215
0216
0217
0218
0219 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, additive_combine_engine, r)
0220 { is >> r._mlcg1 >> std::ws >> r._mlcg2; return is; }
0221
0222
0223
0224
0225
0226 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(additive_combine_engine, x, y)
0227 { return x._mlcg1 == y._mlcg1 && x._mlcg2 == y._mlcg2; }
0228
0229
0230
0231
0232 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(additive_combine_engine)
0233
0234 private:
0235 MLCG1 _mlcg1;
0236 MLCG2 _mlcg2;
0237 };
0238
0239 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
0240 template<class MLCG1, class MLCG2>
0241 const bool additive_combine_engine<MLCG1, MLCG2>::has_fixed_range;
0242 #endif
0243
0244
0245
0246
0247 template<class MLCG1, class MLCG2, typename MLCG1::result_type val = 0>
0248 class additive_combine : public additive_combine_engine<MLCG1, MLCG2>
0249 {
0250 typedef additive_combine_engine<MLCG1, MLCG2> base_t;
0251 public:
0252 typedef typename base_t::result_type result_type;
0253 additive_combine() {}
0254 template<class T>
0255 additive_combine(T& arg) : base_t(arg) {}
0256 template<class T>
0257 additive_combine(const T& arg) : base_t(arg) {}
0258 template<class It>
0259 additive_combine(It& first, It last) : base_t(first, last) {}
0260 };
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 typedef additive_combine_engine<
0273 linear_congruential_engine<uint32_t, 40014, 0, 2147483563>,
0274 linear_congruential_engine<uint32_t, 40692, 0, 2147483399>
0275 > ecuyer1988;
0276
0277 }
0278
0279 using random::ecuyer1988;
0280
0281 }
0282
0283 #endif