/build/rocrand-sFFtDi/rocrand-10.0/library/include/rocrand/rocrand_sobol64.h Source File

/build/rocrand-sFFtDi/rocrand-10.0/library/include/rocrand/rocrand_sobol64.h Source File#

API library: /build/rocrand-sFFtDi/rocrand-10.0/library/include/rocrand/rocrand_sobol64.h Source File
rocrand_sobol64.h
1// Copyright (c) 2021-2026 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_SOBOL64_H_
22#define ROCRAND_SOBOL64_H_
23
24#include <hip/hip_runtime.h>
25
26namespace rocrand_device
27{
28
29template<bool UseSharedVectors>
30struct sobol64_state
31{
32 unsigned long long int d;
33 unsigned long long int i;
34 unsigned long long int vectors[64];
35
36 __forceinline__ __device__ __host__
37 sobol64_state()
38 : d(), i(), vectors()
39 {}
40
41 __forceinline__ __device__ __host__
42 sobol64_state(const unsigned long long int d,
43 const unsigned long long int i,
44 const unsigned long long int* vectors)
45 : d(d), i(i)
46 {
47 for(int k = 0; k < 64; k++)
48 {
49 this->vectors[k] = vectors[k];
50 }
51 }
52};
53
54template<>
55struct sobol64_state<true>
56{
57 unsigned long long int d;
58 unsigned long long int i;
59 const unsigned long long int* vectors;
60
61 __forceinline__ __device__ __host__
62 sobol64_state()
63 : d(), i(), vectors()
64 {}
65
66 __forceinline__ __device__ __host__
67 sobol64_state(const unsigned long long int d,
68 const unsigned long long int i,
69 const unsigned long long int* vectors)
70 : d(d), i(i), vectors(vectors)
71 {}
72};
73
74template<bool UseSharedVectors>
75class sobol64_engine
76{
77public:
78 typedef struct sobol64_state<UseSharedVectors> sobol64_state;
79
80 __forceinline__ __device__ __host__
81 sobol64_engine()
82 {}
83
84 __forceinline__ __device__ __host__
85 sobol64_engine(const unsigned long long int* vectors, const unsigned long long int offset)
86 : m_state(0, 0, vectors)
87 {
88 discard_state(offset);
89 }
90
92 __forceinline__ __device__ __host__
93 void discard(unsigned long long int offset)
94 {
95 discard_state(offset);
96 }
97
98 __forceinline__ __device__ __host__
99 void discard()
100 {
101 discard_state();
102 }
103
105 __forceinline__ __device__ __host__
106 void discard_stride(unsigned long long int stride)
107 {
108 discard_state_power2(stride);
109 }
110
111 __forceinline__ __device__ __host__
112 unsigned long long int operator()()
113 {
114 return this->next();
115 }
116
117 __forceinline__ __device__ __host__
118 unsigned long long int next()
119 {
120 unsigned long long int p = m_state.d;
121 discard_state();
122 return p;
123 }
124
125 __forceinline__ __device__ __host__
126 unsigned long long int current() const
127 {
128 return m_state.d;
129 }
130
131 __forceinline__ __device__ __host__
132 static constexpr bool uses_shared_vectors()
133 {
134 return UseSharedVectors;
135 }
136
137protected:
138 // Advances the internal state by offset times.
139 __forceinline__ __device__ __host__
140 void discard_state(unsigned long long int offset)
141 {
142 m_state.i += offset;
143 const unsigned long long int g = m_state.i ^ (m_state.i >> 1ull);
144 m_state.d = 0;
145 for(int i = 0; i < 64; i++)
146 {
147 m_state.d ^= (g & (1ull << i) ? m_state.vectors[i] : 0ull);
148 }
149 }
150
151 // Advances the internal state to the next state
152 __forceinline__ __device__ __host__
153 void discard_state()
154 {
155 m_state.d ^= m_state.vectors[rightmost_zero_bit(m_state.i)];
156 m_state.i++;
157 }
158
159 __forceinline__ __device__ __host__
160 void discard_state_power2(unsigned long long int stride)
161 {
162 // Leap frog
163 //
164 // T Bradley, J Toit, M Giles, R Tong, P Woodhams
165 // Parallelisation Techniques for Random Number Generators
166 // GPU Computing Gems, 2011
167 //
168 // For power of 2 jumps only 2 bits in Gray code change values
169 // All bits lower than log2(stride) flip 2, 4... times, i.e.
170 // do not change their values.
171
172 // log2(stride) bit
173 m_state.d ^= m_state.vectors[rightmost_zero_bit(~stride) - 1];
174 // the rightmost zero bit of i, not including the lower log2(stride) bits
175 m_state.d ^= m_state.vectors[rightmost_zero_bit(m_state.i | (stride - 1))];
176 m_state.i += stride;
177 }
178
179 // Returns the index of the rightmost zero bit in the binary expansion of
180 // x (Gray code of the current element's index)
181 // NOTE changing unsigned long long int to unit64_t will cause compile failure on device
182 __forceinline__ __device__ __host__
183 unsigned int rightmost_zero_bit(unsigned long long int x)
184 {
185#if defined(__HIP_DEVICE_COMPILE__)
186 unsigned int z = __ffsll(~x);
187 return z ? z - 1 : 0;
188#else
189 if(x == 0)
190 return 0;
191 unsigned long long int y = x;
192 unsigned long long int z = 1;
193 while(y & 1)
194 {
195 y >>= 1;
196 z++;
197 }
198 return z - 1;
199#endif
200 }
201
202protected:
203 // State
204 sobol64_state m_state;
205
206}; // sobol64_engine class
207
208} // end namespace rocrand_device
209
214
216typedef rocrand_device::sobol64_engine<false> rocrand_state_sobol64;
218
229__forceinline__ __device__ __host__
230void rocrand_init(const unsigned long long int* vectors,
231 const unsigned long long int offset,
232 rocrand_state_sobol64* state)
233{
234 *state = rocrand_state_sobol64(vectors, offset);
235}
236
249__forceinline__ __device__ __host__
250unsigned long long int rocrand(rocrand_state_sobol64* state)
251{
252 return state->next();
253}
254
263__forceinline__ __device__ __host__
264void skipahead(unsigned long long int offset, rocrand_state_sobol64* state)
265{
266 return state->discard(offset);
267}
268 // end of group rocranddevice
270
271#endif // ROCRAND_sobol64_H_
__forceinline__ __device__ __host__ void rocrand_init(const unsigned long long int *vectors, const unsigned long long int offset, rocrand_state_sobol64 *state)
Initialize sobol64 state.
Definition rocrand_sobol64.h:230
__forceinline__ __device__ __host__ unsigned long long int rocrand(rocrand_state_sobol64 *state)
Returns uniformly distributed random unsigned long long int value from [0; 2^64 - 1] range.
Definition rocrand_sobol64.h:250
__forceinline__ __device__ __host__ void skipahead(unsigned long long int offset, rocrand_state_sobol64 *state)
Updates sobol64 state to skip ahead by offset elements.
Definition rocrand_sobol64.h:264