1
/* boost random/shuffle_output.hpp header file
3
* Copyright Jens Maurer 2000-2001
4
* Permission to use, copy, modify, sell, and distribute this software
5
* is hereby granted without fee provided that the above copyright notice
6
* appears in all copies and that both that copyright notice and this
7
* permission notice appear in supporting documentation,
9
* Jens Maurer makes no representations about the suitability of this
10
* software for any purpose. It is provided "as is" without express or
13
* See http://www.boost.org for most recent version including documentation.
15
* $Id: shuffle_output.hpp,v 1.1 2004/02/27 03:16:46 pseudonym Exp $
18
* 2001-02-18 moved to individual header files
21
#ifndef BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
22
#define BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
25
#include <algorithm> // std::copy
27
#include <boost/config.hpp>
28
#include <boost/limits.hpp>
29
#include <boost/static_assert.hpp>
30
#include <boost/cstdint.hpp>
31
#include <boost/random/linear_congruential.hpp>
36
// Carter Bays and S.D. Durham 1979
37
template<class UniformRandomNumberGenerator, int k,
38
#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
39
typename UniformRandomNumberGenerator::result_type
47
typedef UniformRandomNumberGenerator base_type;
48
typedef typename base_type::result_type result_type;
50
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
51
BOOST_STATIC_CONSTANT(int, buffer_size = k);
53
shuffle_output() : _rng() { init(); }
54
#if defined(BOOST_MSVC) && _MSC_VER <= 1200
55
// MSVC does not implicitly generate the copy constructor here
56
shuffle_output(const shuffle_output & x)
57
: _rng(x._rng), y(x.y) { std::copy(x.v, x.v+k, v); }
60
explicit shuffle_output(T seed) : _rng(seed) { init(); }
61
explicit shuffle_output(const base_type & rng) : _rng(rng) { init(); }
62
template<class It> shuffle_output(It& first, It last)
63
: _rng(first, last) { init(); }
65
void seed(T s) { _rng.seed(s); init(); }
66
template<class It> void seed(It& first, It last)
68
_rng.seed(first, last);
72
const base_type& base() const { return _rng; }
74
result_type operator()() {
75
// calculating the range every time may seem wasteful. However, this
76
// makes the information locally available for the optimizer.
77
result_type range = max()-min()+1;
78
int j = k*(y-min())/range;
79
// assert(0 <= j && j < k);
85
result_type min() const { return _rng.min(); }
86
result_type max() const { return _rng.max(); }
87
static bool validation(result_type x) { return val == x; }
89
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
91
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
92
template<class CharT, class Traits>
93
friend std::basic_ostream<CharT,Traits>&
94
operator<<(std::basic_ostream<CharT,Traits>& os, const shuffle_output& s)
96
os << s._rng << " " << s.y << " ";
97
for(int i = 0; i < s.buffer_size; ++i)
102
template<class CharT, class Traits>
103
friend std::basic_istream<CharT,Traits>&
104
operator>>(std::basic_istream<CharT,Traits>& is, shuffle_output& s)
106
is >> s._rng >> std::ws >> s.y >> std::ws;
107
for(int i = 0; i < s.buffer_size; ++i)
108
is >> s.v[i] >> std::ws;
113
friend bool operator==(const shuffle_output& x, const shuffle_output& y)
114
{ return x._rng == y._rng && x.y == y.y && std::equal(x.v, x.v+k, y.v); }
115
friend bool operator!=(const shuffle_output& x, const shuffle_output& y)
116
{ return !(x == y); }
118
// Use a member function; Streamable concept not supported.
119
bool operator==(const shuffle_output& rhs) const
120
{ return _rng == rhs._rng && y == rhs.y && std::equal(v, v+k, rhs.v); }
121
bool operator!=(const shuffle_output& rhs) const
122
{ return !(*this == rhs); }
127
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
128
BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
130
result_type range = max()-min();
131
assert(range > 0); // otherwise there would be little choice
132
if(static_cast<unsigned long>(k * range) <
133
static_cast<unsigned long>(range)) // not a sufficient condition
134
// likely overflow with bucket number computation
135
assert(!"overflow will occur");
137
// we cannot use std::generate, because it uses pass-by-value for _rng
138
for(result_type * p = v; p != v+k; ++p)
148
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
149
// A definition is required even for integral static constants
150
template<class UniformRandomNumberGenerator, int k,
151
#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
152
typename UniformRandomNumberGenerator::result_type
157
const bool shuffle_output<UniformRandomNumberGenerator, k, val>::has_fixed_range;
159
template<class UniformRandomNumberGenerator, int k,
160
#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
161
typename UniformRandomNumberGenerator::result_type
166
const int shuffle_output<UniformRandomNumberGenerator, k, val>::buffer_size;
169
} // namespace random
171
// validation by experiment from Harry Erwin's generator.h (private e-mail)
172
typedef random::shuffle_output<
173
random::linear_congruential<uint32_t, 1366, 150889, 714025, 0>,
174
97, 139726> kreutzer1986;
179
#endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP