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