MCKL
Monte Carlo Kernel Library
normal_distribution.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/normal_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_NORMAL_DISTRIBUTION_HPP
33 #define MCKL_RANDOM_NORMAL_DISTRIBUTION_HPP
34 
36 #include <mckl/internal/cblas.hpp>
39 
40 namespace mckl {
41 
42 namespace internal {
43 
44 template <typename RealType>
45 inline bool normal_distribution_check_param(RealType, RealType stddev)
46 {
47  return stddev > 0;
48 }
49 
50 template <std::size_t K, typename RealType, typename RNGType>
52  RNGType &rng, std::size_t n, RealType *r, RealType mean, RealType stddev)
53 {
54  alignas(MCKL_ALIGNMENT) std::array<RealType, K / 2> s;
55  const std::size_t nu = n / 2;
56  RealType *const u1 = r;
57  RealType *const u2 = r + nu;
58  u01_oc_distribution(rng, n, r);
59  log(nu, u1, s.data());
60  mul(nu, static_cast<RealType>(-2), s.data(), s.data());
61  sqrt(nu, s.data(), s.data());
62  mul(nu, const_pi_2<RealType>(), u2, u2);
63  sincos(nu, u2, u1, u2);
64  MCKL_PUSH_CLANG_WARNING("-Wfloat-equal")
65  MCKL_PUSH_INTEL_WARNING(1572) // floating-point comparison
66  if (stddev != 1) {
67  mul(nu, stddev, s.data(), s.data());
68  }
69  if (mean != 0) {
70  muladd(nu, s.data(), u1, mean, u1);
71  muladd(nu, s.data(), u2, mean, u2);
72  } else {
73  mul(nu, s.data(), u1, u1);
74  mul(nu, s.data(), u2, u2);
75  }
78 }
79 
80 } // namespace internal
81 
82 template <typename RealType, typename RNGType>
83 inline void normal_distribution(
84  RNGType &rng, std::size_t n, RealType *r, RealType mean, RealType stddev)
85 {
86  const std::size_t k = BufferSize<RealType>::value;
87  const std::size_t m = n / k;
88  const std::size_t l = n % k;
89  for (std::size_t i = 0; i != m; ++i, r += k) {
90  internal::normal_distribution_impl<k>(rng, k, r, mean, stddev);
91  }
92  internal::normal_distribution_impl<k>(rng, l, r, mean, stddev);
93  if (n % 2 != 0) {
95  RealType u = u01(rng);
96  RealType v = u01(rng);
97  r[l - 1] = mean +
98  stddev * std::sqrt(-2 * std::log(u)) *
99  std::cos(const_pi_2<RealType>() * v);
100  }
101 }
102 
103 template <typename RealType, typename RNGType>
104 inline void normal_distribution(RNGType &rng, std::size_t n, RealType *r,
105  const typename NormalDistribution<RealType>::param_type &param)
106 {
107  normal_distribution(rng, n, r, param.mean(), param.stddev());
108 }
109 
110 MCKL_PUSH_CLANG_WARNING("-Wpadded")
113 template <typename RealType>
114 class NormalDistribution
115 {
118  Normal, normal, RealType, result_type, mean, 0, result_type, stddev, 1)
120 
121  public:
122  result_type min() const
123  {
124  return std::numeric_limits<result_type>::lowest();
125  }
126 
127  result_type max() const { return std::numeric_limits<result_type>::max(); }
128 
129  void reset()
130  {
131  v_ = 0;
132  saved_ = false;
133  }
134 
135  private:
136  template <typename RNGType>
137  result_type generate(RNGType &rng, const param_type &param)
138  {
139  result_type z = 0;
140  if (saved_) {
141  z = v_;
142  saved_ = false;
143  } else {
145  result_type u1 = std::sqrt(-2 * std::log(u01(rng)));
146  result_type u2 = const_pi_2<result_type>() * u01(rng);
147  z = u1 * std::cos(u2);
148  v_ = u1 * std::sin(u2);
149  saved_ = true;
150  }
151 
152  return param.mean() + param.stddev() * z;
153  }
154 }; // class NormalDistribution
156 
158 
159 } // namespace mckl
160 
161 #endif // MCKL_RANDOM_NORMAL_DISTRIBUTION_HPP
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_2( Name, name, T, T1, p1, v1, T2, p2, v2)
void mul(std::size_t n, const float *a, const float *b, float *y)
Definition: vmf.hpp:124
void normal_distribution(MKLEngine< BRNG, Bits > &rng, std::size_t n, float *r, float mean, float stddev)
Definition: mkl.hpp:1386
#define MCKL_PUSH_CLANG_WARNING(warning)
Definition: compiler.h:63
void u01_oc_distribution(RNGType &rng, std::size_t n, RealType *r)
void sin(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:236
void log(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:226
void normal_distribution_impl(RNGType &rng, std::size_t n, RealType *r, RealType mean, RealType stddev)
T muladd(T a, T b, T c)
Definition: vmf.hpp:673
Standard uniform distribution on (0, 1].
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_RAND(Name, T)
void sincos(std::size_t n, const float *a, float *y, float *z)
Definition: vmf.hpp:241
RealType u01(UIntType u)
Convert uniform unsigned integers to floating points within [0, 1].
Definition: u01.hpp:88
#define MCKL_PUSH_INTEL_WARNING(wid)
Definition: compiler.h:88
void sqrt(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:177
void cos(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:234
Definition: mcmc.hpp:40
#define MCKL_POP_CLANG_WARNING
Definition: compiler.h:66
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_ASSERT_REAL_TYPE(Name)
bool normal_distribution_check_param(RealType, RealType stddev)
#define MCKL_POP_INTEL_WARNING
Definition: compiler.h:89
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_MEMBER_2(T1, m1, T2, m2)