File indexing completed on 2025-01-18 09:51:12
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_RANDOM_NIEDERREITER_BASE2_HPP
0010 #define BOOST_RANDOM_NIEDERREITER_BASE2_HPP
0011
0012 #include <boost/random/detail/niederreiter_base2_table.hpp>
0013 #include <boost/random/detail/gray_coded_qrng.hpp>
0014
0015 #include <boost/dynamic_bitset.hpp>
0016
0017 namespace boost {
0018 namespace random {
0019
0020
0021 namespace qrng_detail {
0022 namespace nb2 {
0023
0024
0025 template <typename DynamicBitset>
0026 inline typename DynamicBitset::size_type
0027 bitset_log2(const DynamicBitset& v)
0028 {
0029 if (v.none())
0030 boost::throw_exception( std::invalid_argument("bitset_log2") );
0031
0032 typename DynamicBitset::size_type hibit = v.size() - 1;
0033 while (!v.test(hibit))
0034 --hibit;
0035 return hibit;
0036 }
0037
0038
0039
0040 template <typename PolynomialT, typename DynamicBitset>
0041 inline void modulo2_multiply(PolynomialT P, DynamicBitset& v, DynamicBitset& pt)
0042 {
0043 pt.reset();
0044 for (; P; P >>= 1, v <<= 1)
0045 if (P & 1) pt ^= v;
0046 pt.swap(v);
0047 }
0048
0049
0050
0051
0052
0053
0054 template <typename DynamicBitset>
0055 inline void calculate_v(const DynamicBitset& pb,
0056 typename DynamicBitset::size_type kj,
0057 typename DynamicBitset::size_type pb_degree,
0058 DynamicBitset& v)
0059 {
0060 typedef typename DynamicBitset::size_type size_type;
0061
0062
0063
0064 size_type r = 0;
0065 for ( ; r != kj; ++r)
0066 v.reset(r);
0067
0068
0069
0070
0071 for ( ; r < pb_degree; ++r)
0072 v.set(r);
0073
0074
0075
0076 for ( ; r != v.size(); ++r)
0077 {
0078 bool term = false;
0079 for (typename DynamicBitset::size_type k = 0; k < pb_degree; ++k)
0080 {
0081 term ^= pb.test(k) & v[r + k - pb_degree];
0082 }
0083 v[r] = term;
0084 }
0085 }
0086
0087 }
0088
0089 template<typename UIntType, unsigned w, typename Nb2Table>
0090 struct niederreiter_base2_lattice
0091 {
0092 typedef UIntType value_type;
0093
0094 BOOST_STATIC_ASSERT(w > 0u);
0095 BOOST_STATIC_CONSTANT(unsigned, bit_count = w);
0096
0097 private:
0098 typedef std::vector<value_type> container_type;
0099
0100 public:
0101 explicit niederreiter_base2_lattice(std::size_t dimension)
0102 {
0103 resize(dimension);
0104 }
0105
0106 void resize(std::size_t dimension)
0107 {
0108 typedef boost::dynamic_bitset<> bitset_type;
0109
0110 dimension_assert("Niederreiter base 2", dimension, Nb2Table::max_dimension);
0111
0112
0113 container_type cj(bit_count * dimension);
0114
0115
0116 bitset_type v, pb, tmp;
0117
0118
0119 for (std::size_t dim = 0; dim != dimension; ++dim)
0120 {
0121 const typename Nb2Table::value_type poly = Nb2Table::polynomial(dim);
0122 if (poly > (std::numeric_limits<value_type>::max)()) {
0123 boost::throw_exception( std::range_error("niederreiter_base2: polynomial value outside the given value type range") );
0124 }
0125
0126 const unsigned degree = qrng_detail::msb(poly);
0127 const unsigned space_required = degree * ((bit_count / degree) + 1);
0128
0129 v.resize(degree + bit_count - 1);
0130
0131
0132
0133
0134
0135
0136
0137
0138 pb.resize(space_required); tmp.resize(space_required);
0139
0140 typename bitset_type::size_type kj, pb_degree = 0;
0141 pb.reset();
0142 pb.set(pb_degree);
0143
0144 value_type j = high_bit_mask_t<bit_count - 1>::high_bit;
0145 do
0146 {
0147
0148
0149
0150
0151 kj = pb_degree;
0152
0153
0154
0155
0156 nb2::modulo2_multiply(poly, pb, tmp);
0157 pb_degree += degree;
0158 if (pb_degree >= pb.size()) {
0159
0160
0161 pb_degree = nb2::bitset_log2(pb);
0162 }
0163
0164
0165
0166 nb2::calculate_v(pb, kj, pb_degree, v);
0167
0168
0169
0170
0171
0172
0173 for (unsigned u = 0; j && u != degree; ++u, j >>= 1)
0174 {
0175
0176
0177
0178
0179
0180
0181 for (unsigned r = 0; r != bit_count; ++r) {
0182 value_type& num = cj[dimension * r + dim];
0183
0184 num = (num & ~j) | (-v[r + u] & j);
0185 }
0186 }
0187 } while (j != 0);
0188 }
0189
0190 bits.swap(cj);
0191 }
0192
0193 typename container_type::const_iterator iter_at(std::size_t n) const
0194 {
0195 BOOST_ASSERT(!(n > bits.size()));
0196 return bits.begin() + n;
0197 }
0198
0199 private:
0200 container_type bits;
0201 };
0202
0203 }
0204
0205 typedef detail::qrng_tables::niederreiter_base2 default_niederreiter_base2_table;
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 template<typename UIntType, unsigned w, typename Nb2Table = default_niederreiter_base2_table>
0235 class niederreiter_base2_engine
0236 : public qrng_detail::gray_coded_qrng<
0237 qrng_detail::niederreiter_base2_lattice<UIntType, w, Nb2Table>
0238 >
0239 {
0240 typedef qrng_detail::niederreiter_base2_lattice<UIntType, w, Nb2Table> lattice_t;
0241 typedef qrng_detail::gray_coded_qrng<lattice_t> base_t;
0242
0243 public:
0244
0245
0246
0247 explicit niederreiter_base2_engine(std::size_t s)
0248 : base_t(s)
0249 {}
0250
0251 #ifdef BOOST_RANDOM_DOXYGEN
0252
0253 typedef UIntType result_type;
0254
0255
0256
0257
0258 static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0259 { return (base_t::min)(); }
0260
0261
0262
0263
0264 static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0265 { return (base_t::max)(); }
0266
0267
0268
0269
0270 std::size_t dimension() const { return base_t::dimension(); }
0271
0272
0273
0274
0275
0276 void seed()
0277 {
0278 base_t::seed();
0279 }
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293 void seed(UIntType init)
0294 {
0295 base_t::seed(init);
0296 }
0297
0298
0299
0300
0301
0302
0303
0304 result_type operator()()
0305 {
0306 return base_t::operator()();
0307 }
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 void discard(boost::uintmax_t z)
0321 {
0322 base_t::discard(z);
0323 }
0324
0325
0326 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(niederreiter_base2_engine, x, y)
0327 { return static_cast<const base_t&>(x) == y; }
0328
0329
0330 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(niederreiter_base2_engine)
0331
0332
0333 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, niederreiter_base2_engine, s)
0334 { return os << static_cast<const base_t&>(s); }
0335
0336
0337 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, niederreiter_base2_engine, s)
0338 { return is >> static_cast<base_t&>(s); }
0339
0340 #endif
0341 };
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 typedef niederreiter_base2_engine<boost::uint_least64_t, 64u, default_niederreiter_base2_table> niederreiter_base2;
0355
0356 }
0357
0358 }
0359
0360 #endif