]> git.donarmstrong.com Git - rsem.git/blob - boost/random/additive_combine.hpp
90eff93fe553023510542e2ba197c7bb5ec4155a
[rsem.git] / boost / random / additive_combine.hpp
1 /* boost random/additive_combine.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: additive_combine.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $
11  *
12  * Revision history
13  *  2001-02-18  moved to individual header files
14  */
15
16 #ifndef BOOST_RANDOM_ADDITIVE_COMBINE_HPP
17 #define BOOST_RANDOM_ADDITIVE_COMBINE_HPP
18
19 #include <iostream>
20 #include <algorithm> // for std::min and std::max
21 #include <boost/config.hpp>
22 #include <boost/cstdint.hpp>
23 #include <boost/random/detail/config.hpp>
24 #include <boost/random/linear_congruential.hpp>
25
26 namespace boost {
27 namespace random {
28
29 /**
30  * An instantiation of class template \additive_combine model a
31  * \pseudo_random_number_generator. It combines two multiplicative
32  * \linear_congruential number generators, i.e. those with @c c = 0.
33  * It is described in
34  *
35  *  @blockquote
36  *  "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
37  *  Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
38  *  @endblockquote
39  *
40  * The template parameters MLCG1 and MLCG2 shall denote two different
41  * \linear_congruential number generators, each with c = 0. Each invocation
42  * returns a random number X(n) := (MLCG1(n) - MLCG2(n)) mod (m1 - 1), where
43  * m1 denotes the modulus of MLCG1. 
44  *
45  * The template parameter @c val is the validation value checked by validation.
46  */
47 template<class MLCG1, class MLCG2,
48 #ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
49   typename MLCG1::result_type 
50 #else
51   int32_t
52 #endif
53   val>
54 class additive_combine
55 {
56 public:
57   typedef MLCG1 first_base;
58   typedef MLCG2 second_base;
59   typedef typename MLCG1::result_type result_type;
60 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
61   static const bool has_fixed_range = true;
62   static const result_type min_value = 1;
63   static const result_type max_value = MLCG1::max_value-1;
64 #else
65   enum { has_fixed_range = false };
66 #endif
67   /**
68    * Returns: The smallest value that the generator can produce
69    */
70   result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 1; }
71   /**
72    * Returns: The largest value that the generator can produce
73    */
74   result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_mlcg1.max)()-1; }
75
76   /**
77    * Constructs an \additive_combine generator using the
78    * default constructors of the two base generators.
79    */
80   additive_combine() : _mlcg1(), _mlcg2() { }
81   /**
82    * Constructs an \additive_combine generator, using aseed as
83    * the constructor argument for both base generators.
84    */
85   explicit additive_combine(result_type aseed)
86     : _mlcg1(aseed), _mlcg2(aseed) { }
87   /**
88    * Constructs an \additive_combine generator, using
89    * @c seed1 and @c seed2 as the constructor argument to
90    * the first and second base generators, respectively.
91    */
92   additive_combine(typename MLCG1::result_type seed1, 
93                    typename MLCG2::result_type seed2)
94     : _mlcg1(seed1), _mlcg2(seed2) { }
95   /**
96    * Contructs an \additive_combine generator with
97    * values from the range defined by the input iterators first
98    * and last.  first will be modified to point to the element
99    * after the last one used.
100    *
101    * Throws: @c std::invalid_argument if the input range is too small.
102    *
103    * Exception Safety: Basic
104    */
105   template<class It> additive_combine(It& first, It last)
106     : _mlcg1(first, last), _mlcg2(first, last) { }
107
108   /**
109    * Seeds an \additive_combine generator using the default
110    * seeds of the two base generators.
111    */
112   void seed()
113   {
114     _mlcg1.seed();
115     _mlcg2.seed();
116   }
117
118   /**
119    * Seeds an \additive_combine generator, using @c aseed as the
120    * seed for both base generators.
121    */
122   void seed(result_type aseed)
123   {
124     _mlcg1.seed(aseed);
125     _mlcg2.seed(aseed);
126   }
127
128   /**
129    * Seeds an \additive_combine generator, using @c seed1 and @c seed2 as
130    * the seeds to the first and second base generators, respectively.
131    */
132   void seed(typename MLCG1::result_type seed1,
133             typename MLCG2::result_type seed2)
134   {
135     _mlcg1.seed(seed1);
136     _mlcg2.seed(seed2);
137   }
138
139   /**
140    * Seeds an \additive_combine generator with
141    * values from the range defined by the input iterators first
142    * and last.  first will be modified to point to the element
143    * after the last one used.
144    *
145    * Throws: @c std::invalid_argument if the input range is too small.
146    *
147    * Exception Safety: Basic
148    */
149   template<class It> void seed(It& first, It last)
150   {
151     _mlcg1.seed(first, last);
152     _mlcg2.seed(first, last);
153   }
154
155   /**
156    * Returns: the next value of the generator
157    */
158   result_type operator()() {
159     result_type z = _mlcg1() - _mlcg2();
160     if(z < 1)
161       z += MLCG1::modulus-1;
162     return z;
163   }
164
165   static bool validation(result_type x) { return val == x; }
166
167 #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
168
169 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
170   /**
171    * Writes the state of an \additive_combine generator to a @c
172    * std::ostream.  The textual representation of an \additive_combine
173    * generator is the textual representation of the first base
174    * generator followed by the textual representation of the
175    * second base generator.
176    */
177   template<class CharT, class Traits>
178   friend std::basic_ostream<CharT,Traits>&
179   operator<<(std::basic_ostream<CharT,Traits>& os, const additive_combine& r)
180   { os << r._mlcg1 << " " << r._mlcg2; return os; }
181
182   /**
183    * Reads the state of an \additive_combine generator from a
184    * @c std::istream.
185    */
186   template<class CharT, class Traits>
187   friend std::basic_istream<CharT,Traits>&
188   operator>>(std::basic_istream<CharT,Traits>& is, additive_combine& r)
189   { is >> r._mlcg1 >> std::ws >> r._mlcg2; return is; }
190 #endif
191
192   /**
193    * Returns: true iff the two \additive_combine generators will
194    * produce the same sequence of values.
195    */
196   friend bool operator==(const additive_combine& x, const additive_combine& y)
197   { return x._mlcg1 == y._mlcg1 && x._mlcg2 == y._mlcg2; }
198   /**
199    * Returns: true iff the two \additive_combine generators will
200    * produce different sequences of values.
201    */
202   friend bool operator!=(const additive_combine& x, const additive_combine& y)
203   { return !(x == y); }
204 #else
205   // Use a member function; Streamable concept not supported.
206   bool operator==(const additive_combine& rhs) const
207   { return _mlcg1 == rhs._mlcg1 && _mlcg2 == rhs._mlcg2; }
208   bool operator!=(const additive_combine& rhs) const
209   { return !(*this == rhs); }
210 #endif
211
212 private:
213   MLCG1 _mlcg1;
214   MLCG2 _mlcg2;
215 };
216
217 } // namespace random
218
219 /**
220  * The specialization \ecuyer1988 was suggested in
221  *
222  *  @blockquote
223  *  "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
224  *  Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
225  *  @endblockquote
226  */
227 typedef random::additive_combine<
228     random::linear_congruential<int32_t, 40014, 0, 2147483563, 0>,
229     random::linear_congruential<int32_t, 40692, 0, 2147483399, 0>,
230   2060321752> ecuyer1988;
231
232 } // namespace boost
233
234 #endif // BOOST_RANDOM_ADDITIVE_COMBINE_HPP