32 #ifndef VSMC_RNG_GAMMAK1_H
33 #define VSMC_RNG_GAMMAK1_H
87 #if VSMC_HAS_OPENCL_DOUBLE
89 #define GAMMAK1_2x32 gammak1_2x32_53
90 #define GAMMAK1_2x32_INIT gammak1_2x32_53_init
91 #define GAMMAK1_2x32_RAND gammak1_2x32_53_rand
93 #define GAMMAK1_2x64 gammak1_2x64_53
94 #define GAMMAK1_2x64_INIT gammak1_2x64_53_init
95 #define GAMMAK1_2x64_RAND gammak1_2x64_53_rand
97 #define GAMMAK1_4x32 gammak1_4x32_53
98 #define GAMMAK1_4x32_INIT gammak1_4x32_53_init
99 #define GAMMAK1_4x32_RAND gammak1_4x32_53_rand
101 #define GAMMAK1_4x64 gammak1_4x64_53
102 #define GAMMAK1_4x64_INIT gammak1_4x64_53_init
103 #define GAMMAK1_4x64_RAND gammak1_4x64_53_rand
105 #else // VSMC_HAS_OPENCL_DOUBLE
107 #define GAMMAK1_2x32 gammak1_2x32_24
108 #define GAMMAK1_2x32_INIT gammak1_2x32_24_init
109 #define GAMMAK1_2x32_RAND gammak1_2x32_24_rand
111 #define GAMMAK1_4x32 gammak1_4x32_24
112 #define GAMMAK1_4x32_INIT gammak1_4x32_24_init
113 #define GAMMAK1_4x32_RAND gammak1_4x32_24_rand
115 #endif // VSMC_HAS_OPENCL_DOUBLE
117 #define VSMC_DEFINE_RNG_GAMMAK1(N, W, F, FT) \
119 FT c_shape, c_s2, c_s, c_d, c_b, c_si, c_c, c_q0; \
120 normal01_##N##x##W##_##F rnorm; \
121 } gammak1_##N##x##W##_##F;
123 #define VSMC_DEFINE_RNG_GAMMAK1_INIT(N, W, F, FT) \
124 VSMC_STATIC_INLINE void gammak1_##N##x##W##_##F##_init ( \
125 gammak1_##N##x##W##_##F *rgamma, \
126 cburng##N##x##W##_rng_t *rng, FT shape) \
128 rgamma->c_shape = shape; \
129 normal01_##N##x##W##_##F##_init(&(rgamma->rnorm), rng); \
142 FT c_sqrt32 = 5.6568542494923802; \
143 FT c_s2 = shape - 0.5f; \
144 FT c_s = sqrt(c_s2); \
145 FT c_d = c_sqrt32 - c_s * 12; \
149 FT q1 = 0.04166669; \
150 FT q2 = 0.02083148; \
151 FT q3 = 0.00801191; \
152 FT q4 = 0.00144121; \
156 FT c_q0 = ((((((q7 * r + q6) * r + q5) * r + q4) * r + q3) * r + \
158 if (shape <= 3.686f) { \
159 c_b = 0.463f + c_s + 0.178f * c_s2; \
161 c_c = 0.195f / c_s - 0.079f + 0.16f * c_s; \
162 } else if (shape <= 13.022f) { \
163 c_b = 1.654f + 0.0076f * c_s2; \
164 c_si = 1.68f / c_s + 0.275f; \
165 c_c = 0.062f / c_s + 0.024f; \
169 c_c = 0.1515f / c_s; \
172 rgamma->c_s2 = c_s2; \
176 rgamma->c_si = c_si; \
178 rgamma->c_q0 = c_q0; \
181 #define VSMC_DEFINE_RNG_GAMMAK1_RAND(N, W, F, FT) \
182 VSMC_STATIC_INLINE FT gammak1_##N##x##W##_##F##_rand ( \
183 gammak1_##N##x##W##_##F *rgamma, cburng##N##x##W##_rng_t *rng) \
185 const FT c_shape = rgamma->c_shape; \
186 const FT c_s2 = rgamma->c_s2; \
187 const FT c_s = rgamma->c_s; \
188 const FT c_d = rgamma->c_d; \
189 const FT c_b = rgamma->c_b; \
190 const FT c_si = rgamma->c_si; \
191 const FT c_c = rgamma->c_c; \
192 const FT c_q0 = rgamma->c_q0; \
200 if (c_shape == 1) { \
201 FT u = u01_open_open_##W##_##F(cburng##N##x##W##_rand(rng)); \
206 const FT c_exp_m1 = 0.3678794411714423; \
207 FT b = 1 + c_exp_m1 * c_shape; \
209 FT u = u01_open_open_##W##_##F(cburng##N##x##W##_rand(rng)); \
210 FT v = u01_open_open_##W##_##F(cburng##N##x##W##_rand(rng)); \
214 FT x = -log((b - p) / c_shape); \
215 if (e >= (1 - c_shape) * log(x)) \
218 FT x = exp(log(p) / c_shape); \
225 FT t = normal01_##N##x##W##_##F##_rand(&(rgamma->rnorm), rng); \
226 FT x = c_s + t * 0.5f; \
230 FT u = u01_open_open_##W##_##F(cburng##N##x##W##_rand(rng)); \
231 if (c_d * u <= t * t * t) \
234 const FT a1 = 0.3333333; \
235 const FT a2 = -0.250003; \
236 const FT a3 = 0.2000062; \
237 const FT a4 = -0.1662921; \
238 const FT a5 = 0.1423657; \
239 const FT a6 = -0.1367177; \
240 const FT a7 = 0.1233795; \
243 FT v = t / (c_s + c_s); \
245 if (fabs(v) <= 0.25f) { \
246 q = c_q0 + 0.5f * t * t * \
247 ((((((a7 * v + a6) * v + a5) * v + a4) * \
248 v + a3) * v + a2) * v + a1) * v; \
250 q = c_q0 - c_s * t + 0.25f * t * t + \
251 (c_s2 + c_s2) * log(1 + v); \
254 if (log(1 - u) <= q) \
259 FT e = u01_open_open_##W##_##F(cburng##N##x##W##_rand(rng)); \
260 FT u = u01_open_open_##W##_##F(cburng##N##x##W##_rand(rng)); \
263 FT t = u < 0 ? c_b - c_si * e : c_b + c_si * e; \
265 const FT c_tau = -0.71874483771719; \
269 FT v = t / (c_s + c_s); \
271 if (fabs(v) <= 0.25f) { \
272 q = c_q0 + 0.5f * t * t * \
273 ((((((a7 * v + a6) * v + a5) * v + a4) * \
274 v + a3) * v + a2) * v + a1) * v; \
276 q = c_q0 - c_s * t + 0.25f * t * t + \
277 (c_s2 + c_s2) * log(1 + v); \
281 if (c_c * fabs(u) > expm1(q) * exp(e - 0.5f * t * t)) \
284 FT x = c_s + 0.5f * t; \
304 #if VSMC_HAS_OPENCL_DOUBLE
336 #endif // VSMC_HAS_OPENCL_DOUBLE
338 #endif // VSMC_RNG_GAMMAK1_H
#define VSMC_DEFINE_RNG_GAMMAK1_INIT(N, W, F, FT)
#define VSMC_DEFINE_RNG_GAMMAK1(N, W, F, FT)
#define VSMC_DEFINE_RNG_GAMMAK1_RAND(N, W, F, FT)