MCKL
Monte Carlo Kernel Library
testu01.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/testu01.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_RANDOM_TESTU01_HPP
33 #define MCKL_RANDOM_TESTU01_HPP
34 
36 #include <mckl/random/seed.hpp>
37 
38 extern "C" {
39 
40 #include <TestU01.h>
41 
42 } // extern "C"
43 
44 namespace mckl {
45 
48 class TestU01
49 {
50  public:
51  TestU01(const TestU01 &) = delete;
52  TestU01 &operator=(const TestU01 &) = delete;
53 
54  static TestU01 &instance()
55  {
56  static TestU01 testu01;
57 
58  return testu01;
59  }
60 
62  bool empty() const { return gen_ == nullptr; }
63 
65  template <typename RNGType, typename U01Type>
66  void reset(const std::string &name, bool parallel = false)
67  {
68  parallel ? reset(name, u01_mt<RNGType, U01Type, 1024, 8>) :
69  reset(name, u01_st<RNGType, U01Type, 4096>);
70  }
71 
73  template <typename RNGType, typename U01Type, std::size_t N, std::size_t M>
74  void reset(const std::string &name, bool parallel = false)
75  {
76  parallel ? reset(name, u01_mt<RNGType, U01Type, N, M>) :
77  reset(name, u01_st<RNGType, U01Type, N>);
78  }
79 
81  void reset(const std::string &name, double (*u01)())
82  {
83  release();
84  gen_ =
85  ::unif01_CreateExternGen01(const_cast<char *>(name.c_str()), u01);
86  }
87 
89  void release()
90  {
91  if (gen_ != nullptr)
92  ::unif01_DeleteExternGen01(gen_);
93  gen_ = nullptr;
94  }
95 
97  ::unif01_Gen *gen() const { return gen_; }
98 
100  template <typename Battery>
101  void operator()(Battery &&battery)
102  {
103  battery(gen_);
104  }
105 
114  template <typename BatteryRepeat>
115  void operator()(BatteryRepeat &&battery_repeat, int n)
116  {
117  Vector<int> rep(repeat(n));
118  battery_repeat(gen_, rep.data());
119  }
120 
128  template <typename BatteryRepeat, typename InputIter>
130  BatteryRepeat &&battery_repeat, InputIter first, InputIter last, int n)
131  {
132  Vector<int> rep(repeat(first, last, n));
133  battery_repeat(gen_, rep.data());
134  }
135 
136  private:
137  TestU01() : gen_(nullptr) {}
138 
139  ::unif01_Gen *gen_;
140 
141  template <typename RNGType, typename U01Type, std::size_t N, std::size_t M>
142  static double u01_mt()
143  {
144  MCKL_PUSH_CLANG_WARNING("-Wexit-time-destructors")
145  static std::size_t index = N * M;
146  static Vector<RNGType> rs(M);
147  static Vector<double> result(N * M);
148  static bool init = false;
150 
151  if (index == N * M) {
152  if (!init) {
153  for (auto &rng : rs)
154  rng.seed(Seed<RNGType>::instance().get());
155  init = true;
156  }
157  double *r = result.data();
158  for (std::size_t i = 0; i != M; ++i, r += N) {
159  RNGType rng(std::move(rs[i]));
160  U01Type dist;
161  mckl::rand(rng, dist, N, r);
162  rs[i] = std::move(rng);
163  }
164  index = 0;
165  }
166 
167  return result[index++];
168  }
169 
170  template <typename RNGType, typename U01Type, std::size_t N>
171  static double u01_st()
172  {
173  MCKL_PUSH_CLANG_WARNING("-Wexit-time-destructors")
174  static std::size_t index = N;
175  static RNGType rng(mckl::Seed<RNGType>::instance().get());
176  static mckl::Vector<double> result(N);
178 
179  if (index == N) {
180  U01Type dist;
181  mckl::rand(rng, dist, N, result.data());
182  index = 0;
183  }
184 
185  return result[index++];
186  }
187 
188  static Vector<int> repeat(int n) { return Vector<int>(128, n); }
189 
190  template <typename InputIter>
191  static Vector<int> repeat(InputIter first, InputIter last, int n)
192  {
193  Vector<int> rep(128, 0);
194  for (InputIter iter = first; iter != last; ++iter) {
195  if (*iter < 128)
196  rep[static_cast<std::size_t>(*iter)] += n;
197  }
198 
199  return rep;
200  }
201 }; // class TestU01
202 
203 } // namespace mckl
204 
205 #endif // MCKL_RANDOM_TESTU01_HPP
void reset(const std::string &name, bool parallel=false)
Reset the TestU01 generator to specified RNG and distribution.
Definition: testu01.hpp:74
void reset(const std::string &name, double(*u01)())
Reset the TestU01 generator to specified distribution.
Definition: testu01.hpp:81
#define MCKL_PUSH_CLANG_WARNING(warning)
Definition: compiler.h:63
TestU01 & operator=(const TestU01 &)=delete
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
Definition: memory.hpp:435
::unif01_Gen * gen() const
Get the TestU01 generator.
Definition: testu01.hpp:97
RealType u01(UIntType u)
Convert uniform unsigned integers to floating points within [0, 1].
Definition: u01.hpp:88
void operator()(Battery &&battery)
Apply a battery that accepts a unif01_Gen pointer as input.
Definition: testu01.hpp:101
bool empty() const
Return true if the TestU01 generator is not set or released.
Definition: testu01.hpp:62
void reset(const std::string &name, bool parallel=false)
Reset the TestU01 generator to specified RNG and distribution.
Definition: testu01.hpp:66
Perform TestU01 tests on different RNG and U01 types.
Definition: testu01.hpp:48
void operator()(BatteryRepeat &&battery_repeat, int n)
Apply a battery that accepts a unif01_Gen pointer as the first input, and an array of type int that s...
Definition: testu01.hpp:115
Definition: mcmc.hpp:40
void rand(RNGType &rng, ArcsineDistribution< RealType > &distribution, std::size_t N, RealType *r)
#define MCKL_POP_CLANG_WARNING
Definition: compiler.h:66
static TestU01 & instance()
Definition: testu01.hpp:54
void operator()(BatteryRepeat &&battery_repeat, InputIter first, InputIter last, int n)
Apply a battery that accepts a unif01_Gen pointer as the first input, and an array of type int that s...
Definition: testu01.hpp:129
void release()
Release the TestU01 generator.
Definition: testu01.hpp:89
RNG default seed generator.
Definition: seed.hpp:339