|
1 /* boost random/tausworthe.hpp header file |
|
2 * |
|
3 * Copyright Jens Maurer 2002 |
|
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: linear_feedback_shift.hpp,v 1.12 2005/05/21 15:57:00 dgregor Exp $ |
|
11 * |
|
12 */ |
|
13 |
|
14 #ifndef BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP |
|
15 #define BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP |
|
16 |
|
17 #include <iostream> |
|
18 #include <cassert> |
|
19 #include <stdexcept> |
|
20 #include <boost/config.hpp> |
|
21 #include <boost/static_assert.hpp> |
|
22 #include <boost/limits.hpp> |
|
23 |
|
24 namespace boost { |
|
25 namespace random { |
|
26 |
|
27 // Tausworte 1965 |
|
28 template<class UIntType, int w, int k, int q, int s, UIntType val> |
|
29 class linear_feedback_shift |
|
30 { |
|
31 public: |
|
32 typedef UIntType result_type; |
|
33 // avoid the warning trouble when using (1<<w) on 32 bit machines |
|
34 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); |
|
35 BOOST_STATIC_CONSTANT(int, word_size = w); |
|
36 BOOST_STATIC_CONSTANT(int, exponent1 = k); |
|
37 BOOST_STATIC_CONSTANT(int, exponent2 = q); |
|
38 BOOST_STATIC_CONSTANT(int, step_size = s); |
|
39 |
|
40 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } |
|
41 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return wordmask; } |
|
42 |
|
43 // MSVC 6 and possibly others crash when encountering complicated integral |
|
44 // constant expressions. Avoid the checks for now. |
|
45 // BOOST_STATIC_ASSERT(w > 0); |
|
46 // BOOST_STATIC_ASSERT(q > 0); |
|
47 // BOOST_STATIC_ASSERT(k < w); |
|
48 // BOOST_STATIC_ASSERT(0 < 2*q && 2*q < k); |
|
49 // BOOST_STATIC_ASSERT(0 < s && s <= k-q); |
|
50 |
|
51 explicit linear_feedback_shift(UIntType s0 = 341) : wordmask(0) |
|
52 { |
|
53 // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope |
|
54 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
|
55 BOOST_STATIC_ASSERT(std::numeric_limits<UIntType>::is_integer); |
|
56 BOOST_STATIC_ASSERT(!std::numeric_limits<UIntType>::is_signed); |
|
57 #endif |
|
58 |
|
59 // avoid "left shift count >= with of type" warning |
|
60 for(int i = 0; i < w; ++i) |
|
61 wordmask |= (1u << i); |
|
62 seed(s0); |
|
63 } |
|
64 |
|
65 template<class It> linear_feedback_shift(It& first, It last) : wordmask(0) |
|
66 { |
|
67 // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope |
|
68 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
|
69 BOOST_STATIC_ASSERT(std::numeric_limits<UIntType>::is_integer); |
|
70 BOOST_STATIC_ASSERT(!std::numeric_limits<UIntType>::is_signed); |
|
71 #endif |
|
72 |
|
73 // avoid "left shift count >= with of type" warning |
|
74 for(int i = 0; i < w; ++i) |
|
75 wordmask |= (1u << i); |
|
76 seed(first, last); |
|
77 } |
|
78 |
|
79 void seed(UIntType s0 = 341) { assert(s0 >= (1 << (w-k))); value = s0; } |
|
80 template<class It> void seed(It& first, It last) |
|
81 { |
|
82 if(first == last) |
|
83 throw std::invalid_argument("linear_feedback_shift::seed"); |
|
84 value = *first++; |
|
85 assert(value >= (1 << (w-k))); |
|
86 } |
|
87 |
|
88 result_type operator()() |
|
89 { |
|
90 const UIntType b = (((value << q) ^ value) & wordmask) >> (k-s); |
|
91 const UIntType mask = ( (~static_cast<UIntType>(0)) << (w-k) ) & wordmask; |
|
92 value = ((value & mask) << s) ^ b; |
|
93 return value; |
|
94 } |
|
95 bool validation(result_type x) const { return val == x; } |
|
96 |
|
97 #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE |
|
98 |
|
99 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
|
100 template<class CharT, class Traits> |
|
101 friend std::basic_ostream<CharT,Traits>& |
|
102 operator<<(std::basic_ostream<CharT,Traits>& os, linear_feedback_shift x) |
|
103 { os << x.value; return os; } |
|
104 |
|
105 template<class CharT, class Traits> |
|
106 friend std::basic_istream<CharT,Traits>& |
|
107 operator>>(std::basic_istream<CharT,Traits>& is, linear_feedback_shift& x) |
|
108 { is >> x.value; return is; } |
|
109 #endif |
|
110 |
|
111 friend bool operator==(linear_feedback_shift x, linear_feedback_shift y) |
|
112 { return x.value == y.value; } |
|
113 friend bool operator!=(linear_feedback_shift x, linear_feedback_shift y) |
|
114 { return !(x == y); } |
|
115 #else |
|
116 // Use a member function; Streamable concept not supported. |
|
117 bool operator==(linear_feedback_shift rhs) const |
|
118 { return value == rhs.value; } |
|
119 bool operator!=(linear_feedback_shift rhs) const |
|
120 { return !(*this == rhs); } |
|
121 #endif |
|
122 |
|
123 private: |
|
124 UIntType wordmask; // avoid "left shift count >= width of type" warnings |
|
125 UIntType value; |
|
126 }; |
|
127 |
|
128 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION |
|
129 // A definition is required even for integral static constants |
|
130 template<class UIntType, int w, int k, int q, int s, UIntType val> |
|
131 const bool linear_feedback_shift<UIntType, w, k, q, s, val>::has_fixed_range; |
|
132 template<class UIntType, int w, int k, int q, int s, UIntType val> |
|
133 const int linear_feedback_shift<UIntType, w, k, q, s, val>::word_size; |
|
134 template<class UIntType, int w, int k, int q, int s, UIntType val> |
|
135 const int linear_feedback_shift<UIntType, w, k, q, s, val>::exponent1; |
|
136 template<class UIntType, int w, int k, int q, int s, UIntType val> |
|
137 const int linear_feedback_shift<UIntType, w, k, q, s, val>::exponent2; |
|
138 template<class UIntType, int w, int k, int q, int s, UIntType val> |
|
139 const int linear_feedback_shift<UIntType, w, k, q, s, val>::step_size; |
|
140 #endif |
|
141 |
|
142 } // namespace random |
|
143 } // namespace boost |
|
144 |
|
145 #endif // BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP |