vSMC
vSMC: Scalable Monte Carlo
normal_distribution.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/normal_distribution.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2015, 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 VSMC_RNG_NORMAL_DISTRIBUTION_HPP
33 #define VSMC_RNG_NORMAL_DISTRIBUTION_HPP
34 
38 
39 namespace vsmc
40 {
41 
42 namespace internal
43 {
44 
45 template <typename RealType>
46 inline bool normal_distribution_check_param(RealType, RealType stddev)
47 {
48  return stddev > 0;
49 }
50 
51 } // namespace vsmc::internal
52 
55 template <typename RealType>
57 {
59  Normal, normal, RealType, result_type, mean, 0, result_type, stddev, 1)
60 
61  public:
62  result_type min VSMC_MNE() const
63  {
64  return -std::numeric_limits<result_type>::max VSMC_MNE();
65  }
66 
67  result_type max VSMC_MNE() const
68  {
69  return std::numeric_limits<result_type>::max VSMC_MNE();
70  }
71 
72  void reset()
73  {
74  v_ = 0;
75  saved_ = false;
76  }
77 
78  friend bool operator==(
79  const distribution_type &dist1, const distribution_type &dist2)
80  {
81  if (dist1.param_ != dist2.param_)
82  return false;
83  if (!internal::is_equal(dist1.v_, dist2.v_))
84  return false;
85  if (dist1.saved_ && !dist2.saved_)
86  return false;
87  if (!dist1.saved_ && dist2.saved_)
88  return false;
89  return true;
90  }
91 
92  friend bool operator!=(
93  const distribution_type &dist1, const distribution_type &dist2)
94  {
95  return dist1.param_ != dist2.param_;
96  }
97 
98  template <typename CharT, typename Traits>
99  friend std::basic_ostream<CharT, Traits> &operator<<(
100  std::basic_ostream<CharT, Traits> &os, const distribution_type &dist)
101  {
102  os << dist.param_ << ' ';
103  os << dist.v_ << ' ';
104  os << dist.saved_;
105 
106  return os;
107  }
108 
109  template <typename CharT, typename Traits>
110  friend std::basic_istream<CharT, Traits> &operator>>(
111  std::basic_istream<CharT, Traits> &is, distribution_type &dist)
112  {
113  param_type param;
114  result_type v;
115  bool saved;
116  is >> std::ws >> param;
117  is >> std::ws >> v;
118  is >> std::ws >> saved;
119  if (is.good()) {
120  dist.param_ = param;
121  dist.v_ = v;
122  dist.saved_ = saved;
123  }
124 
125  return is;
126  }
127 
128  private:
129  result_type v_;
130  bool saved_;
131 
132  template <typename RNGType>
133  result_type generate(RNGType &rng, const param_type &param)
134  {
135  result_type z = 0;
136  if (saved_) {
137  z = v_;
138  saved_ = false;
139  } else {
141  result_type u1 = std::sqrt(-2 * std::log(runif(rng)));
142  result_type u2 = const_pi_2<result_type>() * runif(rng);
143  z = u1 * std::cos(u2);
144  v_ = u1 * std::sin(u2);
145  saved_ = true;
146  }
147 
148  return param.mean() + param.stddev() * z;
149  }
150 }; // class NormalDistribution
151 
152 namespace internal
153 {
154 
155 template <std::size_t K, typename RealType, typename RNGType>
157  RNGType &rng, std::size_t n, RealType *r, RealType mean, RealType stddev)
158 {
159  RealType s[K / 2];
160  const std::size_t nu = n / 2;
161  RealType *const u1 = r;
162  RealType *const u2 = r + nu;
163  u01_oc_distribution(rng, n, r);
164  log(nu, u1, s);
165  mul(nu, static_cast<RealType>(-2), s, s);
166  sqrt(nu, s, s);
167  mul(nu, const_pi_2<RealType>(), u2, u2);
168  sincos(nu, u2, u1, u2);
169  mul(nu, stddev, s, s);
170  fma(nu, s, u1, mean, u1);
171  fma(nu, s, u2, mean, u2);
172 }
173 
174 } // namespace vsmc::internal
175 
178 template <typename RealType, typename RNGType>
180  RNGType &rng, std::size_t n, RealType *r, RealType mean, RealType stddev)
181 {
182  const std::size_t k = 1000;
183  const std::size_t m = n / k;
184  const std::size_t l = n % k;
185  for (std::size_t i = 0; i != m; ++i, r += k)
186  internal::normal_distribution_impl<k>(rng, k, r, mean, stddev);
187  internal::normal_distribution_impl<k>(rng, l, r, mean, stddev);
188  if (n % 2 != 0) {
190  RealType u = runif(rng);
191  RealType v = runif(rng);
192  r[l - 1] = mean +
193  stddev * std::sqrt(-2 * std::log(u)) *
194  std::cos(const_pi_2<RealType>() * v);
195  }
196 }
197 
198 template <typename RealType, typename RNGType>
199 inline void rng_rand(RNGType &rng, NormalDistribution<RealType> &dist,
200  std::size_t n, RealType *r)
201 {
202  dist(rng, n, r);
203 }
204 
205 } // namespace vsmc
206 
207 #endif // VSMC_RNG_NORMAL_DISTRIBUTION_HPP
Definition: monitor.hpp:49
Standard uniform distribution with open/closed variants.
Definition: common.hpp:512
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:112
NormalDistribution< RealType > distribution_type
void sqrt(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:129
bool is_equal(const T &a, const T &b)
Definition: common.hpp:333
void normal_distribution_impl(RNGType &rng, std::size_t n, RealType *r, RealType mean, RealType stddev)
void rng_rand(RNGType &rng, BernoulliDistribution< IntType > &dist, std::size_t n, IntType *r)
friend bool operator!=(const distribution_type &dist1, const distribution_type &dist2)
void normal_distribution(RNGType &, std::size_t, RealType *, RealType, RealType)
Generating normal random variates.
#define VSMC_DEFINE_RNG_DISTRIBUTION_2(Name, name, T, T1, p1, v1, T2, p2, v2)
Definition: common.hpp:159
#define VSMC_MNE
Definition: defines.hpp:38
Normal distribution.
Definition: common.hpp:500
void cos(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:152
bool normal_distribution_check_param(RealType, RealType stddev)
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, distribution_type &dist)
void fma(std::size_t n, const T *a, const T *b, const T *c, T *y)
For , compute .
Definition: vmath.hpp:257
void sincos(std::size_t n, const float *a, float *y, float *z)
Definition: vmath.hpp:154
void sin(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:153
friend bool operator==(const distribution_type &dist1, const distribution_type &dist2)
void u01_oc_distribution(RNGType &rng, std::size_t n, RealType *r)
Generate standard uniform random variates on open-closed interval.
void log(std::size_t n, const float *a, float *y)
Definition: vmath.hpp:148
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const distribution_type &dist)