/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-rocrand/checkouts/docs-6.2.0/library/include/rocrand/rocrand_discrete.h Source File

/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-rocrand/checkouts/docs-6.2.0/library/include/rocrand/rocrand_discrete.h Source File#

API library: /home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-rocrand/checkouts/docs-6.2.0/library/include/rocrand/rocrand_discrete.h Source File
API library
rocrand_discrete.h
1 // Copyright (c) 2017-2024 Advanced Micro Devices, Inc. All rights reserved.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #ifndef ROCRAND_DISCRETE_H_
22 #define ROCRAND_DISCRETE_H_
23 
24 #include <math.h>
25 
26 #include "rocrand/rocrand_lfsr113.h"
27 #include "rocrand/rocrand_mrg31k3p.h"
28 #include "rocrand/rocrand_mrg32k3a.h"
29 #include "rocrand/rocrand_mtgp32.h"
30 #include "rocrand/rocrand_philox4x32_10.h"
31 #include "rocrand/rocrand_scrambled_sobol32.h"
32 #include "rocrand/rocrand_scrambled_sobol64.h"
33 #include "rocrand/rocrand_sobol32.h"
34 #include "rocrand/rocrand_sobol64.h"
35 #include "rocrand/rocrand_threefry2x32_20.h"
36 #include "rocrand/rocrand_threefry2x64_20.h"
37 #include "rocrand/rocrand_threefry4x32_20.h"
38 #include "rocrand/rocrand_threefry4x64_20.h"
39 #include "rocrand/rocrand_xorwow.h"
40 
41 #include "rocrand/rocrand_discrete_types.h"
42 
43 // Alias method
44 //
45 // Walker, A. J.
46 // An Efficient Method for Generating Discrete Random Variables with General Distributions, 1977
47 //
48 // Vose M. D.
49 // A Linear Algorithm For Generating Random Numbers With a Given Distribution, 1991
50 
51 namespace rocrand_device {
52 namespace detail {
53 
54 __forceinline__ __device__ __host__ unsigned int
55  discrete_alias(const double x,
56  const unsigned int size,
57  const unsigned int offset,
58  const unsigned int* __restrict__ alias,
59  const double* __restrict__ probability)
60 {
61  // Calculate value using Alias table
62 
63  // x is [0, 1)
64  const double nx = size * x;
65  const double fnx = floor(nx);
66  const double y = nx - fnx;
67  const unsigned int i = static_cast<unsigned int>(fnx);
68  return offset + (y < probability[i] ? i : alias[i]);
69 }
70 
71 __forceinline__ __device__ __host__ unsigned int
72  discrete_alias(const double x, const rocrand_discrete_distribution_st& dis)
73 {
74  return discrete_alias(x, dis.size, dis.offset, dis.alias, dis.probability);
75 }
76 
77 __forceinline__ __device__ __host__ unsigned int
78  discrete_alias(const unsigned int r, const rocrand_discrete_distribution_st& dis)
79 {
80  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
81  const double x = r * inv_double_32;
82  return discrete_alias(x, dis);
83 }
84 
85 // To prevent ambiguity compile error when compiler is facing the type "unsigned long"!!!
86 __forceinline__ __device__ __host__ unsigned int
87  discrete_alias(const unsigned long r, const rocrand_discrete_distribution_st& dis)
88 {
89  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
90  const double x = r * inv_double_32;
91  return discrete_alias(x, dis);
92 }
93 
94 __forceinline__ __device__ __host__ unsigned int
95  discrete_alias(const unsigned long long int r, const rocrand_discrete_distribution_st& dis)
96 {
97  constexpr double inv_double_64 = ROCRAND_2POW64_INV_DOUBLE;
98  const double x = r * inv_double_64;
99  return discrete_alias(x, dis);
100 }
101 
102 __forceinline__ __device__ __host__ unsigned int discrete_cdf(const double x,
103  const unsigned int size,
104  const unsigned int offset,
105  const double* __restrict__ cdf)
106 {
107  // Calculate value using binary search in CDF
108 
109  unsigned int min = 0;
110  unsigned int max = size - 1;
111  do
112  {
113  const unsigned int center = (min + max) / 2;
114  const double p = cdf[center];
115  if(x > p)
116  {
117  min = center + 1;
118  }
119  else
120  {
121  max = center;
122  }
123  }
124  while(min != max);
125 
126  return offset + min;
127 }
128 
129 __forceinline__ __device__ __host__ unsigned int
130  discrete_cdf(const double x, const rocrand_discrete_distribution_st& dis)
131 {
132  return discrete_cdf(x, dis.size, dis.offset, dis.cdf);
133 }
134 
135 __forceinline__ __device__ __host__ unsigned int
136  discrete_cdf(const unsigned int r, const rocrand_discrete_distribution_st& dis)
137 {
138  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
139  const double x = r * inv_double_32;
140  return discrete_cdf(x, dis);
141 }
142 
143 // To prevent ambiguity compile error when compiler is facing the type "unsigned long"!!!
144 __forceinline__ __device__ __host__ unsigned int
145  discrete_cdf(const unsigned long r, const rocrand_discrete_distribution_st& dis)
146 {
147  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
148  const double x = r * inv_double_32;
149  return discrete_cdf(x, dis);
150 }
151 
152 __forceinline__ __device__ __host__ unsigned int
153  discrete_cdf(const unsigned long long int r, const rocrand_discrete_distribution_st& dis)
154 {
155  constexpr double inv_double_64 = ROCRAND_2POW64_INV_DOUBLE;
156  const double x = r * inv_double_64;
157  return discrete_cdf(x, dis);
158 }
159 
160 } // end namespace detail
161 } // end namespace rocrand_device
162 
180 __forceinline__ __device__ __host__ unsigned int
181  rocrand_discrete(rocrand_state_philox4x32_10* state,
182  const rocrand_discrete_distribution discrete_distribution)
183 {
184  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
185 }
186 
199 __forceinline__ __device__ __host__ uint4 rocrand_discrete4(
200  rocrand_state_philox4x32_10* state, const rocrand_discrete_distribution discrete_distribution)
201 {
202  const uint4 u4 = rocrand4(state);
203  return uint4 {
204  rocrand_device::detail::discrete_alias(u4.x, *discrete_distribution),
205  rocrand_device::detail::discrete_alias(u4.y, *discrete_distribution),
206  rocrand_device::detail::discrete_alias(u4.z, *discrete_distribution),
207  rocrand_device::detail::discrete_alias(u4.w, *discrete_distribution)
208  };
209 }
210 
223 __forceinline__ __device__ __host__ unsigned int
224  rocrand_discrete(rocrand_state_mrg31k3p* state,
225  const rocrand_discrete_distribution discrete_distribution)
226 {
227  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
228 }
229 
242 __forceinline__ __device__ __host__ unsigned int
243  rocrand_discrete(rocrand_state_mrg32k3a* state,
244  const rocrand_discrete_distribution discrete_distribution)
245 {
246  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
247 }
248 
261 __forceinline__ __device__ __host__ unsigned int
262  rocrand_discrete(rocrand_state_xorwow* state,
263  const rocrand_discrete_distribution discrete_distribution)
264 {
265  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
266 }
267 
280 __forceinline__ __device__ unsigned int
281  rocrand_discrete(rocrand_state_mtgp32* state,
282  const rocrand_discrete_distribution discrete_distribution)
283 {
284  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
285 }
286 
299 __forceinline__ __device__ __host__ unsigned int
300  rocrand_discrete(rocrand_state_sobol32* state,
301  const rocrand_discrete_distribution discrete_distribution)
302 {
303  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
304 }
305 
318 __forceinline__ __device__ __host__ unsigned int
319  rocrand_discrete(rocrand_state_scrambled_sobol32* state,
320  const rocrand_discrete_distribution discrete_distribution)
321 {
322  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
323 }
324 
337 __forceinline__ __device__ __host__ unsigned int
338  rocrand_discrete(rocrand_state_sobol64* state,
339  const rocrand_discrete_distribution discrete_distribution)
340 {
341  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
342 }
343 
356 __forceinline__ __device__ __host__ unsigned int
357  rocrand_discrete(rocrand_state_scrambled_sobol64* state,
358  const rocrand_discrete_distribution discrete_distribution)
359 {
360  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
361 }
362 
375 __forceinline__ __device__ __host__ unsigned int
376  rocrand_discrete(rocrand_state_lfsr113* state,
377  const rocrand_discrete_distribution discrete_distribution)
378 {
379  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
380 }
381 
394 __forceinline__ __device__ __host__ unsigned int
395  rocrand_discrete(rocrand_state_threefry2x32_20* state,
396  const rocrand_discrete_distribution discrete_distribution)
397 {
398  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
399 }
400 
413 __forceinline__ __device__ __host__ unsigned int
414  rocrand_discrete(rocrand_state_threefry2x64_20* state,
415  const rocrand_discrete_distribution discrete_distribution)
416 {
417  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
418 }
419 
432 __forceinline__ __device__ __host__ unsigned int
433  rocrand_discrete(rocrand_state_threefry4x32_20* state,
434  const rocrand_discrete_distribution discrete_distribution)
435 {
436  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
437 }
438 
451 __forceinline__ __device__ __host__ unsigned int
452  rocrand_discrete(rocrand_state_threefry4x64_20* state,
453  const rocrand_discrete_distribution discrete_distribution)
454 {
455  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
456 }
457  // end of group rocranddevice
459 
460 #endif // ROCRAND_DISCRETE_H_
__forceinline__ __device__ __host__ uint4 rocrand4(rocrand_state_philox4x32_10 *state)
Returns four uniformly distributed random unsigned int values from [0; 2^32 - 1] range.
Definition: rocrand_philox4x32_10.h:386
__forceinline__ __device__ __host__ uint4 rocrand_discrete4(rocrand_state_philox4x32_10 *state, const rocrand_discrete_distribution discrete_distribution)
Returns four discrete distributed unsigned int values.
Definition: rocrand_discrete.h:199
__forceinline__ __device__ __host__ unsigned int rocrand_discrete(rocrand_state_philox4x32_10 *state, const rocrand_discrete_distribution discrete_distribution)
Returns a discrete distributed unsigned int value.
Definition: rocrand_discrete.h:181
__forceinline__ __device__ __host__ unsigned int rocrand(rocrand_state_lfsr113 *state)
Returns uniformly distributed random unsigned int value from [0; 2^32 - 1] range.
Definition: rocrand_lfsr113.h:274
Represents a discrete probability distribution.
Definition: rocrand_discrete_types.h:26
unsigned int size
Number of entries in the probability table.
Definition: rocrand_discrete_types.h:28
unsigned int * alias
Alias table.
Definition: rocrand_discrete_types.h:33
double * cdf
Cumulative distribution function.
Definition: rocrand_discrete_types.h:38
double * probability
Probability data for the alias table.
Definition: rocrand_discrete_types.h:35
unsigned int offset
The distribution can be offset.
Definition: rocrand_discrete_types.h:30