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

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

API library: /home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-rocrand/checkouts/latest/library/include/rocrand/rocrand_discrete.h Source File
API library
rocrand_discrete.h
1 // Copyright (c) 2017-2023 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 #ifndef FQUALIFIERS
25 #define FQUALIFIERS __forceinline__ __device__
26 #endif // FQUALIFIERS
27 
28 #include <math.h>
29 
30 #include "rocrand/rocrand_lfsr113.h"
31 #include "rocrand/rocrand_mrg31k3p.h"
32 #include "rocrand/rocrand_mrg32k3a.h"
33 #include "rocrand/rocrand_mtgp32.h"
34 #include "rocrand/rocrand_philox4x32_10.h"
35 #include "rocrand/rocrand_scrambled_sobol32.h"
36 #include "rocrand/rocrand_scrambled_sobol64.h"
37 #include "rocrand/rocrand_sobol32.h"
38 #include "rocrand/rocrand_sobol64.h"
39 #include "rocrand/rocrand_threefry2x32_20.h"
40 #include "rocrand/rocrand_threefry2x64_20.h"
41 #include "rocrand/rocrand_threefry4x32_20.h"
42 #include "rocrand/rocrand_threefry4x64_20.h"
43 #include "rocrand/rocrand_xorwow.h"
44 
45 #include "rocrand/rocrand_discrete_types.h"
46 #include "rocrand/rocrand_normal.h"
47 #include "rocrand/rocrand_uniform.h"
48 
49 // Alias method
50 //
51 // Walker, A. J.
52 // An Efficient Method for Generating Discrete Random Variables with General Distributions, 1977
53 //
54 // Vose M. D.
55 // A Linear Algorithm For Generating Random Numbers With a Given Distribution, 1991
56 
57 namespace rocrand_device {
58 namespace detail {
59 
60 FQUALIFIERS unsigned int discrete_alias(const double x,
61  const unsigned int size,
62  const unsigned int offset,
63  const unsigned int* __restrict__ alias,
64  const double* __restrict__ probability)
65 {
66  // Calculate value using Alias table
67 
68  // x is [0, 1)
69  const double nx = size * x;
70  const double fnx = floor(nx);
71  const double y = nx - fnx;
72  const unsigned int i = static_cast<unsigned int>(fnx);
73  return offset + (y < probability[i] ? i : alias[i]);
74 }
75 
76 FQUALIFIERS unsigned int discrete_alias(const double x, const rocrand_discrete_distribution_st& dis)
77 {
78  return discrete_alias(x, dis.size, dis.offset, dis.alias, dis.probability);
79 }
80 
82 unsigned int discrete_alias(const unsigned int r, const rocrand_discrete_distribution_st& dis)
83 {
84  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
85  const double x = r * inv_double_32;
86  return discrete_alias(x, dis);
87 }
88 
89 // To prevent ambiguity compile error when compiler is facing the type "unsigned long"!!!
90 FQUALIFIERS unsigned int discrete_alias(const unsigned long r,
92 {
93  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
94  const double x = r * inv_double_32;
95  return discrete_alias(x, dis);
96 }
97 
98 FQUALIFIERS unsigned int discrete_alias(const unsigned long long int r,
100 {
101  constexpr double inv_double_64 = ROCRAND_2POW64_INV_DOUBLE;
102  const double x = r * inv_double_64;
103  return discrete_alias(x, dis);
104 }
105 
106 FQUALIFIERS unsigned int discrete_cdf(const double x,
107  const unsigned int size,
108  const unsigned int offset,
109  const double* __restrict__ cdf)
110 {
111  // Calculate value using binary search in CDF
112 
113  unsigned int min = 0;
114  unsigned int max = size - 1;
115  do
116  {
117  const unsigned int center = (min + max) / 2;
118  const double p = cdf[center];
119  if(x > p)
120  {
121  min = center + 1;
122  }
123  else
124  {
125  max = center;
126  }
127  }
128  while(min != max);
129 
130  return offset + min;
131 }
132 
133 FQUALIFIERS unsigned int discrete_cdf(const double x, const rocrand_discrete_distribution_st& dis)
134 {
135  return discrete_cdf(x, dis.size, dis.offset, dis.cdf);
136 }
137 
139 unsigned int discrete_cdf(const unsigned int r, const rocrand_discrete_distribution_st& dis)
140 {
141  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
142  const double x = r * inv_double_32;
143  return discrete_cdf(x, dis);
144 }
145 
146 // To prevent ambiguity compile error when compiler is facing the type "unsigned long"!!!
147 FQUALIFIERS unsigned int discrete_cdf(const unsigned long r,
149 {
150  constexpr double inv_double_32 = ROCRAND_2POW32_INV_DOUBLE;
151  const double x = r * inv_double_32;
152  return discrete_cdf(x, dis);
153 }
154 
155 FQUALIFIERS unsigned int discrete_cdf(const unsigned long long int r,
157 {
158  constexpr double inv_double_64 = ROCRAND_2POW64_INV_DOUBLE;
159  const double x = r * inv_double_64;
160  return discrete_cdf(x, dis);
161 }
162 
163 } // end namespace detail
164 } // end namespace rocrand_device
165 
184 unsigned int rocrand_discrete(rocrand_state_philox4x32_10 * state, const rocrand_discrete_distribution discrete_distribution)
185 {
186  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
187 }
188 
202 uint4 rocrand_discrete4(rocrand_state_philox4x32_10 * state, const rocrand_discrete_distribution discrete_distribution)
203 {
204  const uint4 u4 = rocrand4(state);
205  return uint4 {
206  rocrand_device::detail::discrete_alias(u4.x, *discrete_distribution),
207  rocrand_device::detail::discrete_alias(u4.y, *discrete_distribution),
208  rocrand_device::detail::discrete_alias(u4.z, *discrete_distribution),
209  rocrand_device::detail::discrete_alias(u4.w, *discrete_distribution)
210  };
211 }
212 
225 FQUALIFIERS unsigned int rocrand_discrete(rocrand_state_mrg31k3p* state,
226  const rocrand_discrete_distribution discrete_distribution)
227 {
228  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
229 }
230 
244 unsigned int rocrand_discrete(rocrand_state_mrg32k3a * state, const rocrand_discrete_distribution discrete_distribution)
245 {
246  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
247 }
248 
262 unsigned int rocrand_discrete(rocrand_state_xorwow * state, const rocrand_discrete_distribution discrete_distribution)
263 {
264  return rocrand_device::detail::discrete_alias(rocrand(state), *discrete_distribution);
265 }
266 
280 unsigned int rocrand_discrete(rocrand_state_mtgp32 * state, const rocrand_discrete_distribution discrete_distribution)
281 {
282  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
283 }
284 
298 unsigned int rocrand_discrete(rocrand_state_sobol32 * state, const rocrand_discrete_distribution discrete_distribution)
299 {
300  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
301 }
302 
316 unsigned int rocrand_discrete(rocrand_state_scrambled_sobol32* state,
317  const rocrand_discrete_distribution discrete_distribution)
318 {
319  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
320 }
321 
334 FQUALIFIERS unsigned int rocrand_discrete(rocrand_state_sobol64* state,
335  const rocrand_discrete_distribution discrete_distribution)
336 {
337  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
338 }
339 
352 FQUALIFIERS unsigned int rocrand_discrete(rocrand_state_scrambled_sobol64* state,
353  const rocrand_discrete_distribution discrete_distribution)
354 {
355  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
356 }
357 
371 unsigned int rocrand_discrete(rocrand_state_lfsr113* state,
372  const rocrand_discrete_distribution discrete_distribution)
373 {
374  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
375 }
376 
389 FQUALIFIERS unsigned int rocrand_discrete(rocrand_state_threefry2x32_20* state,
390  const rocrand_discrete_distribution discrete_distribution)
391 {
392  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
393 }
394 
407 FQUALIFIERS unsigned int rocrand_discrete(rocrand_state_threefry2x64_20* state,
408  const rocrand_discrete_distribution discrete_distribution)
409 {
410  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
411 }
412 
425 FQUALIFIERS unsigned int rocrand_discrete(rocrand_state_threefry4x32_20* state,
426  const rocrand_discrete_distribution discrete_distribution)
427 {
428  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
429 }
430 
443 FQUALIFIERS unsigned int rocrand_discrete(rocrand_state_threefry4x64_20* state,
444  const rocrand_discrete_distribution discrete_distribution)
445 {
446  return rocrand_device::detail::discrete_cdf(rocrand(state), *discrete_distribution);
447 }
448  // end of group rocranddevice
450 
451 #endif // ROCRAND_DISCRETE_H_
FQUALIFIERS 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:202
FQUALIFIERS 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:184
FQUALIFIERS unsigned int rocrand(rocrand_state_lfsr113 *state)
Returns uniformly distributed random unsigned int value from [0; 2^32 - 1] range.
Definition: rocrand_lfsr113.h:253
FQUALIFIERS 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:410
#define FQUALIFIERS
Shorthand for commonly used function qualifiers.
Definition: rocrand_uniform.h:31
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