iutest  1.17.99.14
iutest_random.hpp
[詳解]
1 //======================================================================
2 //-----------------------------------------------------------------------
13 //-----------------------------------------------------------------------
14 //======================================================================
15 #ifndef INCG_IRIS_IUTEST_RANDOM_HPP_89F260D7_9145_4B50_A8F0_B7A2696121B6_
16 #define INCG_IRIS_IUTEST_RANDOM_HPP_89F260D7_9145_4B50_A8F0_B7A2696121B6_
17 
18 //======================================================================
19 // include
20 // IWYU pragma: begin_exports
21 #include "iutest_time.hpp"
22 
23 #if IUTEST_HAS_CXX_HDR_RANDOM
24 # include <random>
25 #endif
26 // IWYU pragma: end_exports
27 
28 namespace iutest {
29 namespace detail
30 {
31 
32 //======================================================================
33 // class
37 class iuRandom
38 {
39 #if IUTEST_HAS_CXX_HDR_RANDOM && defined(IUTEST_USE_RANDOM_ENGINE_TYPENAME)
40  typedef IUTEST_USE_RANDOM_ENGINE_TYPENAME Engine;
41 #else
42  class Engine
43  {
44  public:
45  typedef unsigned int result_type;
46  public:
47  explicit Engine(unsigned int s=0) IUTEST_CXX_NOEXCEPT_SPEC
48  {
49  seed(s);
50  }
51  result_type operator ()()
52  {
53  return gen();
54  }
55  bool operator == (const Engine& rhs)
56  {
57  return m_v1 == rhs.m_v1 && m_v2 == rhs.m_v2 && m_v3 == rhs.m_v3 && m_v4 == rhs.m_v4;
58  }
59  bool operator != (const Engine& rhs)
60  {
61  return m_v1 != rhs.m_v1 || m_v2 != rhs.m_v2 || m_v3 != rhs.m_v3 || m_v4 != rhs.m_v4;
62  }
63  public:
64  void seed(unsigned int s)
65  {
66  m_v4 = s;
67  m_v3 = 1812433253 * ((m_v4 ^ (m_v4 >> 30)) + 1);
68  m_v2 = 1812433253 * ((m_v3 ^ (m_v3 >> 30)) + 2);
69  m_v1 = 1812433253 * ((m_v2 ^ (m_v2 >> 30)) + 3);
70  }
71  void discard(unsigned int z)
72  {
73  for(unsigned int i=0; i < z; ++i)
74  {
75  gen();
76  }
77  }
78  public:
79 #if !defined(IUTEST_NO_INCLASS_MEMBER_INITIALIZATION)
80  static IUTEST_CXX_CONSTEXPR_OR_CONST result_type _Min = 0;
81  static IUTEST_CXX_CONSTEXPR_OR_CONST result_type _Max = static_cast<result_type>(-1);
82 #endif
83 
84  static IUTEST_CXX_CONSTEXPR result_type (min)() { return 0; }
85  static IUTEST_CXX_CONSTEXPR result_type (max)() { return static_cast<result_type>(-1); }
86 
87  private:
88  result_type gen()
89  {
90  const unsigned int t = (m_v1 ^ (m_v1 << 11));
91  m_v1 = m_v2;
92  m_v2 = m_v3;
93  m_v3 = m_v4;
94  m_v4 = (m_v4 ^ (m_v4 >> 19)) ^ (t ^ (t >> 8));
95  return m_v4;
96  }
97  private:
98  unsigned int m_v1, m_v2, m_v3, m_v4;
99  };
100 #endif
101 
102  Engine m_engine;
103 
104 public:
105  typedef unsigned int result_type;
106 
107  static IUTEST_CXX_CONSTEXPR result_type (min)() { return (Engine::min)(); }
108  static IUTEST_CXX_CONSTEXPR result_type (max)() { return (Engine::max)(); }
109 
110 #if defined(__clang__) && (IUTEST_CLANG_MAJOR < 3 || (IUTEST_CLANG_MAJOR == 3 && IUTEST_CLANG_MINOR < 3))
111  static IUTEST_CXX_CONSTEXPR_OR_CONST result_type _Min = Engine::_Min;
112  static IUTEST_CXX_CONSTEXPR_OR_CONST result_type _Max = Engine::_Max;
113 #endif
114 
115 public:
116  iuRandom()
117  {
118  init();
119  }
120 
121  explicit iuRandom(unsigned int seed)
122  {
123  init(seed);
124  }
125 
126 public:
131  void init()
132  {
133  init(GetIndefiniteValue());
134  }
139  void init(unsigned int seed)
140  {
141  m_engine = Engine(seed);
142  }
143 
144 public:
149  result_type genrand()
150  {
151  return m_engine();
152  }
153 
160  result_type genrand(unsigned int max)
161  {
162 #if IUTEST_HAS_CXX_HDR_RANDOM
163  ::std::uniform_int_distribution<unsigned int> d(0, max-1);
164  return d(m_engine);
165 #else
166  return genrand()%max;
167 #endif
168  }
169 
176  template<typename T>
177  T genrand(T max)
178  {
179 #if IUTEST_HAS_CXX_HDR_RANDOM
180  ::std::uniform_int_distribution<T> d(0, max-1);
181  return d(m_engine);
182 #else
183 #if !defined(IUTEST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS)
184  return genrand<T>()%max;
185 #else
186  return genrand(detail::explicit_type<result_type>())%max;
187 #endif
188 #endif
189  }
190 
196  float genrandf()
197  {
198 #if IUTEST_HAS_CXX_HDR_RANDOM
199  return ::std::uniform_real_distribution<float>(0.0f, 1.0f)(m_engine);
200 #else
201  return static_cast<float>(genrand())*(1.0f/4294967295.0f);
202 #endif
203  }
204 
209  template<typename T>
210  T genrand(IUTEST_EXPLICIT_TEMPLATE_TYPE_(T))
211  {
212  return static_cast<T>(genrand( static_cast<unsigned int>( static_cast<T>(-1) ) ));
213  }
214 
215 #if IUTEST_HAS_CLASS_MEMBER_TEMPLATE_SPECIALIZATION && (defined(_MSC_VER) && _MSC_VER < 1300)
216  template<>float genrand<float>(IUTEST_EXPLICIT_TEMPLATE_TYPE_(float)) { return genrandf(); }
217  template<>double genrand<double>(IUTEST_EXPLICIT_TEMPLATE_TYPE_(double)) { return static_cast<double>(genrandf()); }
218 #endif
219 
220 public:
221  result_type operator ()()
222  {
223  return genrand();
224  }
225  result_type operator ()(unsigned int max)
226  {
227  return genrand(max);
228  }
229 
230 public:
231  template<typename It>
232  void shuffle(It first, It last)
233  {
234 #if IUTEST_HAS_CXX_HDR_RANDOM
235  ::std::shuffle(first, last, m_engine);
236 #else
237  ::std::random_shuffle(first, last, *this);
238 #endif
239  }
240 };
241 
242 #if !(defined(_MSC_VER) && _MSC_VER < 1300)
243 
244 #define IIUT_WORKAROUND_GENRAND(type) \
245  template<> inline type iuRandom::genrand<type>(IUTEST_EXPLICIT_TEMPLATE_TYPE_(type))
246 
247 IIUT_WORKAROUND_GENRAND(Int64) { return (static_cast<Int64>(genrand()) << 32) | genrand(); }
248 IIUT_WORKAROUND_GENRAND(UInt64) { return (static_cast<UInt64>(genrand()) << 32) | genrand(); }
249 IIUT_WORKAROUND_GENRAND(float) { return genrandf(); }
250 IIUT_WORKAROUND_GENRAND(double) { return static_cast<double>(genrandf()); }
251 
252 #undef IIUT_WORKAROUND_GENRAND
253 
254 #endif
255 
259 template<typename T>
260 class iuTypedRandom
261 {
262  typedef T result_type;
263 public:
264  iuTypedRandom() {}
265  explicit iuTypedRandom(unsigned int seed)
266  : m_rnd(seed) {}
267 
268  result_type operator ()()
269  {
270  return genrand();
271  }
272 
273  result_type operator ()(result_type max)
274  {
275  return genrand(max);
276  }
277 
278  result_type genrand()
279  {
280 #if !defined(IUTEST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS)
281 #if defined(__MWERKS__)
282  return m_rnd.template genrand<result_type>();
283 #else
284  return m_rnd.genrand<result_type>();
285 #endif
286 #else
287  return m_rnd.genrand(detail::explicit_type<result_type>());
288 #endif
289  }
290 
291  result_type genrand(result_type max)
292  {
293  return m_rnd.genrand(max);
294  }
295 private:
296  iuRandom m_rnd;
297 };
298 
299 } // end of namespace detail
300 } // end of namespace iutest
301 
302 #endif // INCG_IRIS_IUTEST_RANDOM_HPP_89F260D7_9145_4B50_A8F0_B7A2696121B6_
#define IUTEST_USE_RANDOM_ENGINE_TYPENAME
iutest で使用する乱数エンジンを指定します
Definition: iutest_config.hpp:782
#define IUTEST_CXX_CONSTEXPR_OR_CONST
constexpr or const
Definition: iutest_compiler.hpp:386
#define IUTEST_CXX_CONSTEXPR
constexpr
Definition: iutest_compiler.hpp:372
#define IUTEST_CXX_NOEXCEPT_SPEC
noexcept specification definition
Definition: iutest_compiler.hpp:811
time utility
iutest root namespace
Definition: iutest_charcode.hpp:33
detail::type_fit_t< 8 >::UInt UInt64
64 bit 符号なし整数型
Definition: iutest_defs.hpp:505
detail::type_fit_t< 8 >::Int Int64
64 bit 符号付き整数型
Definition: iutest_defs.hpp:504