source: NonGTP/Boost/boost/random/shuffle_output.hpp @ 857

Revision 857, 5.5 KB checked in by igarcia, 18 years ago (diff)
Line 
1/* boost random/shuffle_output.hpp header file
2 *
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)
7 *
8 * See http://www.boost.org for most recent version including documentation.
9 *
10 * $Id: shuffle_output.hpp,v 1.9 2004/07/27 03:43:32 dgregor Exp $
11 *
12 * Revision history
13 *  2001-02-18  moved to individual header files
14 */
15
16#ifndef BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
17#define BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
18
19#include <iostream>
20#include <algorithm>     // std::copy
21#include <cassert>
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>
27
28namespace boost {
29namespace random {
30
31// Carter Bays and S.D. Durham 1979
32template<class UniformRandomNumberGenerator, int k,
33#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
34  typename UniformRandomNumberGenerator::result_type
35#else
36  uint32_t
37#endif
38  val = 0>
39class shuffle_output
40{
41public:
42  typedef UniformRandomNumberGenerator base_type;
43  typedef typename base_type::result_type result_type;
44
45  BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
46  BOOST_STATIC_CONSTANT(int, buffer_size = k);
47
48  shuffle_output() : _rng() { init(); }
49#if defined(BOOST_MSVC) && _MSC_VER <= 1200
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); }
53#endif
54  template<class T>
55  explicit shuffle_output(T seed) : _rng(seed) { 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(); }
60  template<class T>
61  void seed(T s) { _rng.seed(s); init(); }
62  template<class It> void seed(It& first, It last)
63  {
64    _rng.seed(first, last);
65    init();
66  }
67
68  const base_type& base() const { return _rng; }
69
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);
76    y = v[j];
77    v[j] = _rng();
78    return y;
79  }
80
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; }
84
85#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
86
87#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
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)
91  {
92    os << s._rng << " " << s.y << " ";
93    for(int i = 0; i < s.buffer_size; ++i)
94      os << s.v[i] << " ";
95    return os;
96  }
97
98  template<class CharT, class Traits>
99  friend std::basic_istream<CharT,Traits>&
100  operator>>(std::basic_istream<CharT,Traits>& is, shuffle_output& s)
101  {
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;
105    return is;
106  }
107#endif
108
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); }
113#else
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); }
119#endif
120private:
121  void init()
122  {
123#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
124    BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
125#endif
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");
132
133    // we cannot use std::generate, because it uses pass-by-value for _rng
134    for(result_type * p = v; p != v+k; ++p)
135      *p = _rng();
136    y = _rng();
137  }
138
139  base_type _rng;
140  result_type v[k];
141  result_type y;
142};
143
144#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
145//  A definition is required even for integral static constants
146template<class UniformRandomNumberGenerator, int k,
147#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
148  typename UniformRandomNumberGenerator::result_type
149#else
150  uint32_t
151#endif
152  val>
153const bool shuffle_output<UniformRandomNumberGenerator, k, val>::has_fixed_range;
154
155template<class UniformRandomNumberGenerator, int k,
156#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
157  typename UniformRandomNumberGenerator::result_type
158#else
159  uint32_t
160#endif
161  val>
162const int shuffle_output<UniformRandomNumberGenerator, k, val>::buffer_size;
163#endif
164
165} // namespace random
166
167// validation by experiment from Harry Erwin's generator.h (private e-mail)
168typedef random::shuffle_output<
169    random::linear_congruential<uint32_t, 1366, 150889, 714025, 0>,
170  97, 139726> kreutzer1986;
171
172
173} // namespace boost
174
175#endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
Note: See TracBrowser for help on using the repository browser.