MCKL
Monte Carlo Kernel Library
run_test.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/run_test.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_RUN_TEST_HPP
33 #define MCKL_RANDOM_RUN_TEST_HPP
34 
37 
38 namespace mckl {
39 
40 namespace internal {
41 
42 template <bool>
44 
45 template <>
46 class RunTestCheck<true>
47 {
48  public:
49  template <typename ResultType>
50  static bool eval(ResultType u, ResultType v)
51  {
52  return u > v;
53  }
54 }; // class RunTestCheck
55 
56 template <>
57 class RunTestCheck<false>
58 {
59  public:
60  template <typename ResultType>
61  static bool eval(ResultType u, ResultType v)
62  {
63  return u < v;
64  }
65 }; // class RunTestCheck
66 
67 template <bool, bool>
69 
70 template <bool Up>
71 class RunTestImpl<false, Up> : public ChiSquaredTest<RunTestImpl<false, Up>>
72 {
73  public:
74  RunTestImpl(std::size_t n) : n_(n) {}
75 
77 
78  template <typename RNGType, typename DistributionType>
79  double operator()(RNGType &rng, DistributionType &distribution)
80  {
81  using result_type = typename DistributionType::result_type;
82 
83  std::array<double, 6> count;
84  std::fill(count.begin(), count.end(), 0);
85 
86  const std::size_t t = 5;
87  std::size_t s = 0;
88  result_type v = distribution(rng);
89  while (s < n_) {
90  std::size_t r = 0;
91  while (true) {
92  ++r;
93  ++s;
94  result_type u = v;
95  v = distribution(rng);
96  if (RunTestCheck<Up>::eval(u, v)) {
97  break;
98  }
99  if (s == n_) {
100  break;
101  }
102  }
103  count[std::min(r - 1, t)] += 1;
104  }
105 
106  static const std::array<double, 36> a = {
107  {4529.3536459687906886, 9044.9020785000773816,
108  13567.945220995269025, 18091.267213474662936,
109  22614.713867746890457, 27892.158836517771651,
110  9044.9020785000773816, 18097.025434456939714,
111  27139.455190145025166, 36186.649289760956163,
112  45233.819845609141668, 55788.831062952543501,
113  13567.945220995269025, 27139.455190145025166,
114  40721.332025378211539, 54281.265638700444264,
115  67852.044551180596848, 83684.570464780923545,
116  18091.267213474662936, 36186.649289760956163,
117  54281.265638700444264, 72413.608184786274684,
118  90470.078876317476369, 111580.11003176274101,
119  22614.713867746890457, 45233.819845609141668,
120  67852.044551180596848, 90470.078876317476369,
121  113261.81500341715234, 139475.55458338270984,
122  27892.158836517771651, 55788.831062952543501,
123  83684.570464780923545, 111580.11003176274101,
124  139475.55458338270984, 172860.17010641275243}};
125 
126  static const std::array<double, 6> b = {
127  {0.16666666666666666667, 0.20833333333333333333,
128  0.091666666666666666667, 0.026388888888888888889,
129  0.0057539682539682539683, 0.0011904761904761904762}};
130 
131  muladd(
132  6, -static_cast<double>(n_), b.data(), count.data(), count.data());
133 
134  std::array<double, 36> c;
135  std::size_t k = 0;
136  for (std::size_t i = 0; i != 6; ++i) {
137  for (std::size_t j = 0; j != 6; ++j) {
138  c[k++] = count[i] * count[j];
139  }
140  }
141  mul(36, a.data(), c.data(), c.data());
142 
143  return std::accumulate(c.begin(), c.end(), 0.0) / (n_ - 6);
144  }
145 
146  double degree_of_freedom() const { return 6; }
147 
148  private:
149  std::size_t n_;
150 }; // class RunTestImpl
151 
152 template <bool Up>
153 class RunTestImpl<true, Up> : public ChiSquaredTest<RunTestImpl<true, Up>>
154 {
155  public:
156  RunTestImpl(std::size_t n) : n_(n) {}
157 
159 
160  template <typename RNGType, typename DistributionType>
161  double operator()(RNGType &rng, DistributionType &distribution)
162  {
163  using result_type = typename DistributionType::result_type;
164 
165  const std::size_t t = 5;
166  std::array<double, 6> count;
167  std::fill(count.begin(), count.end(), 0);
168 
169  double s = 0;
170  result_type v = distribution(rng);
171  while (s < n_) {
172  std::size_t r = 0;
173  while (true) {
174  if (r > n_) {
175  return 0;
176  }
177  result_type u = v;
178  v = distribution(rng);
179  if (RunTestCheck<Up>::eval(u, v)) {
180  count[std::min(r, t)] += 1;
181  ++s;
182  v = distribution(rng);
183  break;
184  }
185  ++r;
186  }
187  }
188 
189  double n = static_cast<double>(n_);
190  std::array<double, 6> np = {
191  {n / 2, n / 3, n / 8, n / 30, n / 144, n / 720}};
192 
193  return this->stat(t + 1, count.data(), np.data());
194  }
195 
196  double degree_of_freedom() const { return 5; }
197 
198  private:
199  std::size_t n_;
200 }; // class RunTestImpl
201 
202 } // namespace internal
203 
209 template <bool Independent, bool Up = true>
211 
212 } // namespace mckl
213 
214 #endif // MCKL_RANDOM_RUN_TEST_HPP
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmf.hpp:124
static bool eval(ResultType u, ResultType v)
Definition: run_test.hpp:61
static bool eval(ResultType u, ResultType v)
Definition: run_test.hpp:50
T muladd(T a, T b, T c)
Definition: vmf.hpp:673
double operator()(RNGType &rng, DistributionType &distribution)
Definition: run_test.hpp:79
double operator()(RNGType &rng, DistributionType &distribution)
Definition: run_test.hpp:161
#define MCKL_DEFINE_RANDOM_TEST_OPERATOR(ResultType)
Definition: mcmc.hpp:40
Tests based on the -distribution.