1 /* boost random/shuffle_output.hpp header file
3 * Copyright Jens Maurer 2000-2001
4 * Distributed under the Boost Software License, Version 1.0. (See
5 * accompanying file LICENSE_1_0.txt or copy at
6 * http://www.boost.org/LICENSE_1_0.txt)
8 * See http://www.boost.org for most recent version including documentation.
13 * 2001-02-18 moved to individual header files
16 #ifndef BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
17 #define BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
20 #include <algorithm> // std::copy
22 #include <boost/config.hpp>
23 #include <boost/limits.hpp>
24 #include <boost/static_assert.hpp>
25 #include <boost/cstdint.hpp>
26 #include <boost/random/linear_congruential.hpp>
31 // Carter Bays and S.D. Durham 1979
32 template<class UniformRandomNumberGenerator
, int k
,
33 #ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
34 typename
UniformRandomNumberGenerator::result_type
42 typedef UniformRandomNumberGenerator base_type
;
43 typedef typename
base_type::result_type result_type
;
45 BOOST_STATIC_CONSTANT(bool, has_fixed_range
= false);
46 BOOST_STATIC_CONSTANT(int, buffer_size
= k
);
48 shuffle_output() : _rng() { init(); }
49 #if defined(BOOST_MSVC) && _MSC_VER < 1300
50 // MSVC does not implicitly generate the copy constructor here
51 shuffle_output(const shuffle_output
& x
)
52 : _rng(x
._rng
), y(x
.y
) { std::copy(x
.v
, x
.v
+k
, v
); }
55 explicit shuffle_output(T s
) : _rng(s
) { init(); }
56 explicit shuffle_output(const base_type
& rng
) : _rng(rng
) { init(); }
57 template<class It
> shuffle_output(It
& first
, It last
)
58 : _rng(first
, last
) { init(); }
59 void seed() { _rng
.seed(); init(); }
61 void seed(T s
) { _rng
.seed(s
); init(); }
62 template<class It
> void seed(It
& first
, It last
)
64 _rng
.seed(first
, last
);
68 const base_type
& base() const { return _rng
; }
70 result_type
operator()() {
71 // calculating the range every time may seem wasteful. However, this
72 // makes the information locally available for the optimizer.
73 result_type range
= (max
)()-(min
)()+1;
74 int j
= k
*(y
-(min
)())/range
;
75 // assert(0 <= j && j < k);
81 result_type min
BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_rng
.min
)(); }
82 result_type max
BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_rng
.max
)(); }
83 static bool validation(result_type x
) { return val
== x
; }
85 #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
87 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
88 template<class CharT
, class Traits
>
89 friend std::basic_ostream
<CharT
,Traits
>&
90 operator<<(std::basic_ostream
<CharT
,Traits
>& os
, const shuffle_output
& s
)
92 os
<< s
._rng
<< " " << s
.y
<< " ";
93 for(int i
= 0; i
< s
.buffer_size
; ++i
)
98 template<class CharT
, class Traits
>
99 friend std::basic_istream
<CharT
,Traits
>&
100 operator>>(std::basic_istream
<CharT
,Traits
>& is
, shuffle_output
& s
)
102 is
>> s
._rng
>> std::ws
>> s
.y
>> std::ws
;
103 for(int i
= 0; i
< s
.buffer_size
; ++i
)
104 is
>> s
.v
[i
] >> std::ws
;
109 friend bool operator==(const shuffle_output
& x
, const shuffle_output
& y
)
110 { return x
._rng
== y
._rng
&& x
.y
== y
.y
&& std::equal(x
.v
, x
.v
+k
, y
.v
); }
111 friend bool operator!=(const shuffle_output
& x
, const shuffle_output
& y
)
112 { return !(x
== y
); }
114 // Use a member function; Streamable concept not supported.
115 bool operator==(const shuffle_output
& rhs
) const
116 { return _rng
== rhs
._rng
&& y
== rhs
.y
&& std::equal(v
, v
+k
, rhs
.v
); }
117 bool operator!=(const shuffle_output
& rhs
) const
118 { return !(*this == rhs
); }
123 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
124 BOOST_STATIC_ASSERT(std::numeric_limits
<result_type
>::is_integer
);
126 result_type range
= (max
)()-(min
)();
127 assert(range
> 0); // otherwise there would be little choice
128 if(static_cast<unsigned long>(k
* range
) <
129 static_cast<unsigned long>(range
)) // not a sufficient condition
130 // likely overflow with bucket number computation
131 assert(!"overflow will occur");
133 // we cannot use std::generate, because it uses pass-by-value for _rng
134 for(result_type
* p
= v
; p
!= v
+k
; ++p
)
144 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
145 // A definition is required even for integral static constants
146 template<class UniformRandomNumberGenerator
, int k
,
147 #ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
148 typename
UniformRandomNumberGenerator::result_type
153 const bool shuffle_output
<UniformRandomNumberGenerator
, k
, val
>::has_fixed_range
;
155 template<class UniformRandomNumberGenerator
, int k
,
156 #ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
157 typename
UniformRandomNumberGenerator::result_type
162 const int shuffle_output
<UniformRandomNumberGenerator
, k
, val
>::buffer_size
;
165 } // namespace random
167 // validation by experiment from Harry Erwin's generator.h (private e-mail)
168 typedef random::shuffle_output
<
169 random::linear_congruential
<uint32_t, 1366, 150889, 714025, 0>,
170 97, 139726> kreutzer1986
;
175 #endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP