MCKL
Monte Carlo Kernel Library
sampling_distribution.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/sampling_distribution.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_SAMPLING_DISTRIBUTION_HPP
33 #define MCKL_RANDOM_SAMPLING_DISTRIBUTION_HPP
34 
38 
39 namespace mckl {
40 
43 template <typename IntType>
44 class SamplingDistribution
45 {
47  public:
48  using result_type = IntType;
50 
51  class param_type
52  {
53  public:
54  using result_type = IntType;
56 
57  explicit param_type(result_type n = 1, result_type m = 1)
58  : n_(n), m_(m)
59  {
60  }
61 
62  result_type n() const { return n_; }
63  result_type m() const { return m_; }
64 
65  friend bool operator==(
66  const param_type &param1, const param_type &param2)
67  {
68  return param1.n_ == param2.n_ && param1.m_ == param2.m_;
69  }
70 
71  friend bool operator!=(
72  const param_type &param1, const param_type &param2)
73  {
74  return !(param1 == param2);
75  }
76 
77  template <typename CharT, typename Traits>
78  friend std::basic_ostream<CharT, Traits> &operator<<(
79  std::basic_ostream<CharT, Traits> &os, const param_type &param)
80  {
81  if (!os)
82  return os;
83 
84  os << param.n_ << ' ';
85  os << param.m_;
86 
87  return os;
88  }
89 
90  template <typename CharT, typename Traits>
91  friend std::basic_istream<CharT, Traits> &operator>>(
92  std::basic_istream<CharT, Traits> &is, param_type &param)
93  {
94  if (!is)
95  return is;
96 
97  result_type n;
98  result_type m;
99  is >> std::ws >> n >> m;
100 
101  if (is) {
102  if (n >= m && m > 0) {
103  param.n_ = n;
104  param.m_ = m;
105  } else {
106  is.setstate(std::ios_base::failbit);
107  }
108  }
109 
110  return is;
111  }
112 
113  private:
114  result_type n_;
115  result_type m_;
116 
117  friend distribution_type;
118  }; // class param_type
119 
121  : param_(n, m)
122  {
123  }
124 
125  void min(result_type *r) const
126  {
127  for (result_type i = 0; i != m(); ++i)
128  *r++ = i;
129  }
130 
131  void max(result_type *r) const
132  {
133  for (result_type i = n() - m(); i != n(); ++i)
134  *r++ = i;
135  }
136 
137  result_type n() const { return param_.n_; }
138 
139  result_type m() const { return param_.m_; }
140 
141  template <typename RNGType>
142  void operator()(RNGType &rng, result_type *r) const
143  {
144  const result_type n = param_.n_;
145  const result_type m = param_.m_;
146  result_type t = 0;
147  result_type s = 0;
149 
150  while (true) {
151  double u = u01(rng);
152  if ((n - t) * u >= m - s) {
153  ++t;
154  continue;
155  }
156  *r++ = t;
157  ++t;
158  ++s;
159  if (s >= m)
160  return;
161  }
162  }
163 
164  friend bool operator==(
165  const distribution_type &dist1, const distribution_type &dist2)
166  {
167  return dist1.param_ == dist2.param_;
168  }
169 
170  friend bool operator!=(
171  const distribution_type &dist1, const distribution_type &dist2)
172  {
173  return !(dist1 == dist2);
174  }
175 
176  template <typename CharT, typename Traits>
177  friend std::basic_ostream<CharT, Traits> &operator<<(
178  std::basic_ostream<CharT, Traits> &os, const distribution_type &dist)
179  {
180  os << dist.param_;
181 
182  return os;
183  }
184 
185  template <typename CharT, typename Traits>
186  friend std::basic_istream<CharT, Traits> &operator>>(
187  std::basic_istream<CharT, Traits> &is, distribution_type &dist)
188  {
189  is >> std::ws >> dist.param_;
190  if (is)
191  dist.reset();
192 
193  return is;
194  }
195 
196  private:
197  param_type param_;
198 }; // class SamplingDistribution
199 
200 } // namespace mckl
201 
202 #endif // MCKL_RANDOM_SAMPLING_DISTRIBUTION_HPP
Standard uniform distribution on [0, 1)
Drawing a subset without replacement.
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, distribution_type &dist)
friend bool operator==(const param_type &param1, const param_type &param2)
RealType u01(UIntType u)
Convert uniform unsigned integers to floating points within [0, 1].
Definition: u01.hpp:88
void max(result_type *r) const
void operator()(RNGType &rng, result_type *r) const
SamplingDistribution(result_type n=1, result_type m=1)
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const param_type &param)
SamplingDistribution< IntType > distribution_type
Definition: mcmc.hpp:40
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const distribution_type &dist)
void min(result_type *r) const
friend bool operator!=(const distribution_type &dist1, const distribution_type &dist2)
param_type(result_type n=1, result_type m=1)
friend bool operator!=(const param_type &param1, const param_type &param2)
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, param_type &param)
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_ASSERT_INT_TYPE(Name, MinBits)
friend bool operator==(const distribution_type &dist1, const distribution_type &dist2)