2
Copyright 2010-2011, D. E. Shaw Research.
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are
9
* Redistributions of source code must retain the above copyright
10
notice, this list of conditions, and the following disclaimer.
12
* Redistributions in binary form must reproduce the above copyright
13
notice, this list of conditions, and the following disclaimer in the
14
documentation and/or other materials provided with the distribution.
16
* Neither the name of D. E. Shaw Research nor the names of its
17
contributors may be used to endorse or promote products derived from
18
this software without specific prior written permission.
20
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
#ifndef __Engine_dot_hpp_
33
#define __Engine_dot_hpp_
35
#include "../features/compilerfeatures.h"
42
#if R123_USE_CXX11_TYPE_TRAITS
43
#include <type_traits>
48
If G satisfies the requirements of a CBRNG, and has a ctr_type whose
49
value_type is an unsigned integral type, then Engine<G> satisfies
50
the requirements of a C++0x "Uniform Random Number Engine" and can
51
be used in any context where such an object is expected.
53
Note that wrapping a counter based RNG with a traditional API in
54
this way obscures much of the power of counter based PRNGs.
55
Nevertheless, it may be of value in applications that are already
56
coded to work with the C++0x random number engines.
58
The MicroURNG template in MicroURNG.hpp
59
provides the more limited functionality of a C++0x "Uniform
60
Random Number Generator", but leaves the application in control
61
of counters and keys and hence may be preferable to the Engine template.
62
For example, a MicroURNG allows one to use C++0x "Random Number
63
Distributions" without giving up control over the counters
67
template<typename CBRNG>
69
typedef CBRNG cbrng_type;
70
typedef typename CBRNG::ctr_type ctr_type;
71
typedef typename CBRNG::key_type key_type;
72
typedef typename CBRNG::ukey_type ukey_type;
73
typedef typename ctr_type::value_type result_type;
74
typedef size_t elem_type;
90
explicit Engine() : b(), c(), elem() {
95
explicit Engine(result_type r) : b(), c(), elem() {
96
ukey_type x = {{typename ukey_type::value_type(r)}};
100
// 26.5.3 says that the SeedSeq templates shouldn't particpate in
101
// overload resolution unless the type qualifies as a SeedSeq.
102
// How that is determined is unspecified, except that "as a
103
// minimum a type shall not qualify as a SeedSeq if it is
104
// implicitly convertible to a result_type."
106
// First, we make sure that even the non-const copy constructor
107
// works as expected. In addition, if we've got C++0x
108
// type_traits, we use enable_if and is_convertible to implement
109
// the convertible-to-result_type restriction. Otherwise, the
110
// template is unconditional and will match in some surpirsing
111
// and undesirable situations.
112
Engine(Engine& e) : b(e.b), ukey(e.ukey), c(e.c), elem(e.elem){
116
Engine(const Engine& e) : b(e.b), ukey(e.ukey), c(e.c), elem(e.elem){
121
template <typename SeedSeq>
122
explicit Engine(SeedSeq &s
123
#if R123_USE_CXX11_TYPE_TRAITS
124
, typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
128
ukey = ukey_type::seed(s);
131
void seed(result_type r){
134
template <typename SeedSeq>
136
#if R123_USE_CXX11_TYPE_TRAITS
137
, typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
145
friend bool operator==(const Engine& lhs, const Engine& rhs){
146
return lhs.c==rhs.c && lhs.elem == rhs.elem && lhs.ukey == rhs.ukey;
148
friend bool operator!=(const Engine& lhs, const Engine& rhs){
149
return lhs.c!=rhs.c || lhs.elem != rhs.elem || lhs.ukey!=rhs.ukey;
152
friend std::ostream& operator<<(std::ostream& os, const Engine& be){
153
return os << be.c << " " << be.ukey << " " << be.elem;
156
friend std::istream& operator>>(std::istream& is, Engine& be){
157
is >> be.c >> be.ukey >> be.elem;
163
// The <random> shipped with MacOS Xcode 4.5.2 imposes a
164
// non-standard requirement that URNGs also have static data
165
// members: _Min and _Max. Later versions of libc++ impose the
166
// requirement only when constexpr isn't supported. Although the
167
// Xcode 4.5.2 requirement is clearly non-standard, it is unlikely
168
// to be fixed and it is very easy work around. We certainly
169
// don't want to go to great lengths to accommodate every buggy
170
// library we come across, but in this particular case, the effort
171
// is low and the benefit is high, so it's worth doing. Thanks to
172
// Yan Zhou for pointing this out to us. See similar code in
174
const static result_type _Min = 0;
175
const static result_type _Max = ~((result_type)0);
177
static R123_CONSTEXPR result_type min R123_NO_MACRO_SUBST () { return _Min; }
178
static R123_CONSTEXPR result_type max R123_NO_MACRO_SUBST () { return _Max; }
180
result_type operator()(){
181
if( c.size() == 1 ) // short-circuit the scalar case. Compilers aren't mind-readers.
182
return b(c.incr(), key)[0];
184
v = b(c.incr(), key);
190
void discard(R123_ULONG_LONG skip){
191
// don't forget: elem counts down
192
size_t nelem = c.size();
193
size_t sub = skip % nelem;
204
//--------------------------
205
// Some bonus methods, not required for a Random Number
208
// Constructors and seed() method for ukey_type seem useful
209
// We need const and non-const to supersede the SeedSeq template.
210
explicit Engine(const ukey_type &uk) : key(uk), ukey(uk), c(), elem(){}
211
explicit Engine(ukey_type &uk) : key(uk), ukey(uk), c(), elem(){}
212
void seed(const ukey_type& uk){
215
void seed(ukey_type& uk){
219
// Forward the e(counter) to the CBRNG we are templated
220
// on, using the current value of the key.
221
ctr_type operator()(const ctr_type& c) const{
225
// Since you can seed *this with a ukey_type, it seems reasonable
226
// to allow the caller to know what seed/ukey *this is using.
227
ukey_type getseed() const{
231
// Maybe the caller want's to know the details of
232
// the internal state, e.g., so it can call a different
233
// bijection with the same counter.
234
std::pair<ctr_type, elem_type> getcounter() const {
235
return make_pair(c, elem);
239
void setcounter(const ctr_type& _c, elem_type _elem){
240
static const size_t nelem = c.size();
242
throw std::range_error("Engine::setcounter called with elem out of range");