MCKL
Monte Carlo Kernel Library
u01_distribution.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/u01_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_U01_DISTRIBUTION_HPP
33 #define MCKL_RANDOM_U01_DISTRIBUTION_HPP
34 
36 #include <mckl/random/u01.hpp>
38 
41 #ifndef MCKL_U01_USE_FIXED_POINT
42 #define MCKL_U01_USE_FIXED_POINT 0
43 #endif
44 
47 #ifndef MCKL_U01_USE_64BITS_DOUBLE
48 #define MCKL_U01_USE_64BITS_DOUBLE 0
49 #endif
50 
51 #define MCKL_DEFINE_RANDOM_U01_DISTRIBUTION(Name, name) \
52  template <typename RealType> \
53  class Name##Distribution \
54  { \
55  MCKL_DEFINE_RANDOM_DISTRIBUTION_ASSERT_REAL_TYPE(Name) \
56  MCKL_DEFINE_RANDOM_DISTRIBUTION_0(Name, name, RealType) \
57  MCKL_DEFINE_RANDOM_DISTRIBUTION_MEMBER_0 \
58  \
59  public: \
60  result_type min() const { return 0; } \
61  \
62  result_type max() const { return 1; } \
63  \
64  void reset() {} \
65  \
66  private: \
67  template <typename RNGType> \
68  result_type generate(RNGType &rng, const param_type &) \
69  { \
70  using UIntType = \
71  typename internal::U01UIntType<RNGType, RealType>; \
72  \
73  UniformBitsDistribution<UIntType> ubits; \
74  \
75  return name<UIntType, result_type>(ubits(rng)); \
76  } \
77  };
78 
79 #define MCKL_DEFINE_RANDOM_U01_DISTRIBUTION_IMPL(name) \
80  template <std::size_t K, typename RealType, typename RNGType> \
81  inline void name##_distribution_impl( \
82  RNGType &rng, std::size_t n, RealType *r) \
83  { \
84  using UIntType = U01UIntType<RNGType, RealType>; \
85  \
86  alignas(MCKL_ALIGNMENT) std::array<UIntType, K> s; \
87  uniform_bits_distribution(rng, n, s.data()); \
88  name<UIntType, RealType>(n, s.data(), r); \
89  }
90 
91 namespace mckl {
92 
93 namespace internal {
94 
95 #if MCKL_U01_USE_64BITS_DOUBLE
96 
97 template <typename RNGType, typename RealType>
98 using U01UIntType = std::conditional_t<
99  (RNGTraits<RNGType>::bits >= 64 ||
100  std::is_same<typename std::remove_cv_t<RealType>,
101  long double>::value ||
102  std::is_same<typename std::remove_cv_t<RealType>, double>::value),
104 
105 #else // MCKL_U01_USE_64BITS_DOUBLE
106 
107 template <typename RNGType, typename RealType>
108 using U01UIntType =
109  std::conditional_t<(RNGTraits<RNGType>::bits >= 64 ||
110  std::is_same<RealType, long double>::value),
112 
113 #endif // MCKL_U01_USE_64BITS_DOUBLE
114 
115 template <std::size_t K, typename RealType, typename RNGType>
117  RNGType &rng, std::size_t n, RealType *r)
118 {
119  using UIntType = U01UIntType<RNGType, RealType>;
120 
121  constexpr int W = std::numeric_limits<UIntType>::digits;
122  constexpr int M = std::numeric_limits<RealType>::digits;
123  constexpr int P = (M + W - 1) / W;
124  constexpr int Q = 1 > P ? 1 : P;
125 
126  alignas(MCKL_ALIGNMENT) std::array<UIntType, K * Q> s;
127  uniform_bits_distribution(rng, n * Q, s.data());
128  u01_canonical<UIntType, RealType, Q>(n, s.data(), r);
129 }
130 
135 
136 } // namespace internal
137 
143 
146 template <typename RealType>
148 {
150  MCKL_DEFINE_RANDOM_DISTRIBUTION_0(U01Canonical, u01_canonical, RealType)
152 
153  public:
154  result_type min() const { return 0; }
155  result_type max() const { return 1; }
156 
157  void reset() {}
158 
159  private:
160  template <typename RNGType>
161  result_type generate(RNGType &rng, const param_type &)
162  {
164 
165  constexpr int W = std::numeric_limits<UIntType>::digits;
166  constexpr int M = std::numeric_limits<RealType>::digits;
167  constexpr int P = (M + W - 1) / W;
168  constexpr int Q = 1 > P ? 1 : P;
169 
170  std::array<UIntType, Q> u;
171  generate<0>(rng, u, std::true_type());
172 
173  return u01_canonical<UIntType, RealType, Q>(u.data());
174  }
175 
176  template <std::size_t, typename RNGType, typename UIntType, std::size_t Q>
177  void generate(RNGType &, std::array<UIntType, Q> &, std::false_type)
178  {
179  }
180 
181  template <std::size_t N, typename RNGType, typename UIntType,
182  std::size_t Q>
183  void generate(RNGType &rng, std::array<UIntType, Q> &u, std::true_type)
184  {
186  std::get<N>(u) = ubits(rng);
187  generate<N + 1>(rng, u, std::integral_constant<bool, N + 1 < Q>());
188  }
189 }; // class U01CanonicalDistribution
190 
194 
198 
202 
206 
212 
213 #if MCKL_U01_USE_FIXED_POINT
214 
215 template <typename RealType>
217 
218 template <typename RealType, typename RNGType>
219 inline void u01_distribution(RNGType &rng, std::size_t n, RealType *r)
220 {
221  u01_co_distribution(rng, n, r);
222 }
223 
224 #else // MCKL_U01_USE_FIXED_POINT
225 
226 template <typename RealType>
228 
229 template <typename RealType, typename RNGType>
230 inline void u01_distribution(RNGType &rng, std::size_t n, RealType *r)
231 {
232  u01_canonical_distribution(rng, n, r);
233 }
234 
235 #endif // MCKL_U01_USE_FIXED_POINT
236 
237 } // namespace mckl
238 
239 #endif // MCKL_RANDOM_U01_DISTRIBUTION_HPP
std::conditional_t<(RNGTraits< RNGType >::bits >=64||std::is_same< RealType, long double >::value), std::uint64_t, std::uint32_t > U01UIntType
Standard uniform distribution on [0, 1)
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_BATCH_0(Name, name, T)
#define MCKL_DEFINE_RANDOM_U01_DISTRIBUTION_IMPL(name)
uint uint32_t
Definition: opencl.h:41
ulong uint64_t
Definition: opencl.h:42
void uniform_bits_distribution(RNGType &rng, std::size_t n, UIntType *r)
RealType u01_cc(UIntType u)
Convert uniform unsigned integers to floating points on [0, 1].
Definition: u01.hpp:120
RealType u01_oc(UIntType u)
Convert uniform unsigned integers to floating points on (0, 1].
Definition: u01.hpp:136
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_RAND(Name, T)
#define MCKL_DEFINE_RANDOM_U01_DISTRIBUTION(Name, name)
void u01_canonical_distribution(RNGType &rng, std::size_t n, RealType *r)
RealType u01_co(UIntType u)
Convert uniform unsigned integers to floating points on [0, 1)
Definition: u01.hpp:128
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_0(Name, name, T)
void u01_co_distribution(RNGType &rng, std::size_t n, RealType *r)
Definition: mcmc.hpp:40
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
Standard uniform distribution on [0, 1)
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_MEMBER_0
RealType u01_canonical(const UIntType *u)
Convert uniform multiple unsigned integers to one floating points within [0, 1].
Definition: u01.hpp:185
RealType u01_oo(UIntType u)
Convert uniform unsigned integers to floating points on (0, 1)
Definition: u01.hpp:144
#define MCKL_DEFINE_RANDOM_DISTRIBUTION_ASSERT_REAL_TYPE(Name)
void u01_canonical_distribution_impl(RNGType &rng, std::size_t n, RealType *r)
static constexpr int bits
void u01_distribution(RNGType &rng, std::size_t n, RealType *r)