vSMC  v3.0.0
Scalable Monte Carlo
u01_distribution.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/u01_distribution.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, 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_U01_DISTRIBUTION_HPP
33 #define VSMC_RNG_U01_DISTRIBUTION_HPP
34 
36 #include <vsmc/rng/u01.hpp>
38 
41 #ifndef VSMC_RNG_U01_USE_FIXED_POINT
42 #define VSMC_RNG_U01_USE_FIXED_POINT 1
43 #endif
44 
47 #ifndef VSMC_RNG_U01_USE_64BITS_DOUBLE
48 #define VSMC_RNG_U01_USE_64BITS_DOUBLE 0
49 #endif
50 
51 #define VSMC_DEFINE_U01_DISTRIBUTION(Name, name) \
52  template <typename RealType> \
53  class Name##Distribution \
54  { \
55  VSMC_DEFINE_RNG_DISTRIBUTION_0( \
56  Name, name, RealType, floating_point, FLOATING_POINT) \
57  VSMC_DEFINE_RNG_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 VSMC_DEFINE_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  Array<UIntType, K> s; \
87  uniform_bits_distribution(rng, n, s.data()); \
88  name<UIntType, RealType>(n, s.data(), r); \
89  }
90 
91 namespace vsmc
92 {
93 
94 namespace internal
95 {
96 
97 #if VSMC_RNG_U01_USE_64BITS_DOUBLE
98 
99 template <typename RNGType, typename RealType>
100 using U01UIntType =
101  typename std::conditional<(RNGTraits<RNGType>::bits >= 64 ||
102  std::is_same<RealType, long double>::value ||
103  std::is_same<RealType, double>::value),
105 
106 #else // VSMC_RNG_U01_USE_64BITS_DOUBLE
107 
108 template <typename RNGType, typename RealType>
109 using U01UIntType =
110  typename std::conditional<(RNGTraits<RNGType>::bits >= 64 ||
111  std::is_same<RealType, long double>::value),
113 
114 #endif // VSMC_RNG_U01_USE_64BITS_DOUBLE
115 
116 } // namespace vsmc::internal
117 
121 
125 
129 
133 
134 #if VSMC_RNG_U01_USE_FIXED_POINT
135 
136 template <typename RealType>
137 class U01Distribution : public U01CODistribution<RealType>
138 {
139 }; // class U01Distribution
140 
141 #else // VSMC_RNG_U01_USE_FIXED_POINT
142 
145 template <typename RealType>
146 class U01Distribution
147 {
149  U01, u01, RealType, floating_point, FLOATING_POINT)
150 
151  public:
152  result_type min() const { return 0; }
153  result_type max() const { return 1; }
154 
155  void reset() {}
156 
157  private:
158  template <typename RNGType>
159  result_type generate(RNGType &rng, const param_type &)
160  {
161  return generate<0>(rng, std::true_type());
162  }
163 
164  template <std::size_t, typename RNGType>
165  result_type generate(RNGType &, std::false_type)
166  {
167  return 0;
168  }
169 
170  template <std::size_t N, typename RNGType>
171  result_type generate(RNGType &rng, std::true_type)
172  {
174 
176 
177  static constexpr int W = std::numeric_limits<UIntType>::digits;
178  static constexpr int M = std::numeric_limits<RealType>::digits;
179  static constexpr int P = (W + M - 1) / W;
180  static constexpr int Q = 1 > P ? 1 : P;
181 
182  return static_cast<RealType>(ubits(rng)) *
183  internal::U01Pow2Inv<RealType, (Q - N) * W>::value +
184  generate<N + 1>(rng, std::integral_constant<bool, N + 1 < Q>());
185  }
186 }; // class U01Distribution
187 
188 #endif // VSMC_RNG_U01_USE_FIXED_POINT
189 
190 namespace internal
191 {
192 
197 
198 #if VSMC_RNG_U01_USE_FIXED_POINT
199 
200 template <std::size_t K, typename RealType, typename RNGType>
201 inline void u01_distribution_impl(RNGType &rng, std::size_t n, RealType *r)
202 {
203  u01_co_distribution_impl<K>(rng, n, r);
204 }
205 
206 #else // VSMC_RNG_U01_USE_FIXED_POINT
207 
208 template <std::size_t, typename RealType, typename UIntType>
209 inline RealType u01_distribution_impl(const UIntType *, std::false_type)
210 {
211  return 0;
212 }
213 
214 template <std::size_t N, typename RealType, typename UIntType>
215 inline RealType u01_distribution_impl(const UIntType *u, std::true_type)
216 {
217  static constexpr int W = std::numeric_limits<UIntType>::digits;
218  static constexpr int M = std::numeric_limits<RealType>::digits;
219  static constexpr int P = (M + W - 1) / W;
220  static constexpr int Q = 1 > P ? 1 : P;
221 
222  return static_cast<RealType>(u[N]) *
223  U01Pow2Inv<RealType, (Q - N) * W>::value +
224  u01_distribution_impl<N + 1, RealType>(
225  u, std::integral_constant<bool, N + 1 < Q>());
226 }
227 
228 template <std::size_t K, typename RealType, typename RNGType>
229 inline void u01_distribution_impl(RNGType &rng, std::size_t n, RealType *r)
230 {
231  using UIntType = U01UIntType<RNGType, RealType>;
232 
233  static constexpr int W = std::numeric_limits<UIntType>::digits;
234  static constexpr int M = std::numeric_limits<RealType>::digits;
235  static constexpr int P = (M + W - 1) / W;
236  static constexpr int Q = 1 > P ? 1 : P;
237 
239  uniform_bits_distribution(rng, n * Q, s.data());
240  const UIntType *u = s.data();
241  for (std::size_t i = 0; i != n; ++i, u += Q)
242  r[i] = u01_distribution_impl<0, RealType>(u, std::true_type());
243 }
244 
245 #endif // VSMC_RNG_U01_USE_FIXED_POINT
246 
247 } // namespace vsmc::internal
248 
253 
258 
263 
268 
273 
274 } // namespace vsmc
275 
276 #endif // VSMC_RNG_U01_HPP
Definition: monitor.hpp:48
RealType u01_oo(UIntType u) noexcept
Convert uniform unsigned integers to floating points on (0, 1)
Definition: u01.hpp:267
#define VSMC_DEFINE_RNG_DISTRIBUTION_RAND_0(Name, name, T)
#define VSMC_DEFINE_RNG_DISTRIBUTION_0(Name, name, T, t, Type)
uint uint32_t
Definition: opencl.h:41
ulong uint64_t
Definition: opencl.h:42
RealType u01_co(UIntType u) noexcept
Convert uniform unsigned integers to floating points on [0, 1)
Definition: u01.hpp:251
#define VSMC_DEFINE_U01_DISTRIBUTION(Name, name)
RealType u01(UIntType u) noexcept
Convert uniform unsigned integers to floating points within [0, 1].
Definition: u01.hpp:213
#define VSMC_DEFINE_RNG_DISTRIBUTION_IMPL_0(name)
RealType u01_oc(UIntType u) noexcept
Convert uniform unsigned integers to floating points on (0, 1].
Definition: u01.hpp:259
#define VSMC_DEFINE_U01_DISTRIBUTION_IMPL(name)
RealType u01_cc(UIntType u) noexcept
Convert uniform unsigned integers to floating points on [0, 1].
Definition: u01.hpp:243
typename std::conditional<(RNGTraits< RNGType >::bits >=64||std::is_same< RealType, long double >::value), std::uint64_t, std::uint32_t >::type U01UIntType
void uniform_bits_distribution(RNGType &, std::size_t, UIntType *)
std::array with proper alignment
Uniform bits distribution.
void u01_distribution_impl(RNGType &rng, std::size_t n, RealType *r)
Standard uniform distribution on [0, 1)