11 integer,
parameter :: dp = kind(0.0d0)
14 integer,
parameter :: i4 = selected_int_kind(9)
17 integer,
parameter :: i8 = selected_int_kind(18)
22 integer(i8),
private :: s(2) = [123456789_i8, 987654321_i8]
24 procedure, non_overridable :: set_seed
25 procedure, non_overridable :: jump
26 procedure, non_overridable :: int_4
27 procedure, non_overridable :: int_8
28 procedure, non_overridable :: unif_01
29 procedure, non_overridable :: unif_01_vec
30 procedure, non_overridable :: normal
31 procedure, non_overridable :: two_normals
32 procedure, non_overridable :: poisson
33 procedure, non_overridable :: circle
34 procedure, non_overridable :: sphere
35 procedure, non_overridable :: next
40 type(
rng_t),
allocatable :: rngs(:)
42 procedure, non_overridable :: init_parallel
51#if defined(__NVCOMPILER) || (defined(USE_INTRINSIC_SHIFT) && USE_INTRINSIC_SHIFT==0)
54 function shiftl(val, shift)
result(res_value)
55 integer(i8),
intent(in) :: val
56 integer,
intent(in) :: shift
57 integer(i8) :: res_value
62 integer(i8) :: bit_mask1, bit_mask2
66 bit_mask2=-bit_mask1-1
70 res_value = ior(lshift(iand(val, bit_mask1), shift),bit_mask2)
72 res_value = lshift(val, shift)
78 function shiftr(val, shift)
result(res_value)
79 integer(i8),
intent(in) :: val
80 integer,
intent(in) :: shift
81 integer(i8) :: res_value
86 integer(i8) :: bit_mask1, bit_mask2
90 bit_mask2=-bit_mask1-1
93 res_value = ior(rshift(iand(val, bit_mask1), shift),bit_mask2)
95 res_value = rshift(val, shift)
104 subroutine init_parallel(self, n_proc, rng)
105 class(
prng_t),
intent(inout) :: self
106 type(
rng_t),
intent(inout) :: rng
107 integer,
intent(in) :: n_proc
110 allocate(self%rngs(n_proc))
114 self%rngs(n) = self%rngs(n-1)
115 call self%rngs(n)%jump()
117 end subroutine init_parallel
120 subroutine set_seed(self, the_seed)
121 class(
rng_t),
intent(inout) :: self
122 integer(i8),
intent(in) :: the_seed(2)
128 end subroutine set_seed
133 subroutine jump(self)
134 class(
rng_t),
intent(inout) :: self
136 integer(i8) :: global_time(2), dummy
139 integer(i8),
parameter :: jmp_c(2) = &
140 (/-4707382666127344949_i8, -2852180941702784734_i8/)
145 if (iand(jmp_c(i),
shiftl(1_i8, b)) /= 0)
then
146 global_time = ieor(global_time, self%s)
156 integer(i4) function int_4(self)
157 class(
rng_t),
intent(inout) :: self
158 int_4 = int(self%next(), i4)
162 integer(i8) function int_8(self)
163 class(
rng_t),
intent(inout) :: self
168 real(dp) function unif_01(self)
169 class(
rng_t),
intent(inout) :: self
174 x = ior(
shiftl(1023_i8, 52), shiftr(x, 12))
175 unif_01 = transfer(x, tmp) - 1.0_dp
179 subroutine unif_01_vec(self, rr)
180 class(
rng_t),
intent(inout) :: self
181 real(dp),
intent(out) :: rr(:)
185 rr(i) = self%unif_01()
187 end subroutine unif_01_vec
191 function two_normals(self)
result(rands)
192 class(
rng_t),
intent(inout) :: self
193 real(dp) :: rands(2), sum_sq
196 rands(1) = 2 * self%unif_01() - 1
197 rands(2) = 2 * self%unif_01() - 1
198 sum_sq = sum(rands**2)
199 if (sum_sq < 1.0_dp .and. sum_sq > 0.0_dp)
exit
201 rands = rands * sqrt(-2 * log(sum_sq) / sum_sq)
202 end function two_normals
205 real(dp) function normal(self)
206 class(
rng_t),
intent(inout) :: self
209 rands = self%two_normals()
215 function poisson(self, lambda)
result(rr)
216 class(
rng_t),
intent(inout) :: self
217 real(dp),
intent(in) :: lambda
227 p = p * self%unif_01()
232 function circle(self, radius)
result(xy)
233 class(
rng_t),
intent(inout) :: self
234 real(dp),
intent(in) :: radius
235 real(dp) :: rands(2), xy(2)
240 rands(1) = 2 * self%unif_01() - 1
241 rands(2) = 2 * self%unif_01() - 1
242 sum_sq = sum(rands**2)
243 if (sum_sq <= 1)
exit
246 xy(1) = (rands(1)**2 - rands(2)**2) / sum_sq
247 xy(2) = 2 * rands(1) * rands(2) / sum_sq
252 function sphere(self, radius)
result(xyz)
253 class(
rng_t),
intent(inout) :: self
254 real(dp),
intent(in) :: radius
255 real(dp) :: rands(2), xyz(3)
256 real(dp) :: sum_sq, tmp_sqrt
260 rands(1) = 2 * self%unif_01() - 1
261 rands(2) = 2 * self%unif_01() - 1
262 sum_sq = sum(rands**2)
263 if (sum_sq <= 1)
exit
266 tmp_sqrt = sqrt(1 - sum_sq)
267 xyz(1:2) = 2 * rands(1:2) * tmp_sqrt
268 xyz(3) = 1 - 2 * sum_sq
273 function next(self)
result(res)
274 class(
rng_t),
intent(inout) :: self
276 integer(i8) :: global_time(2)
279 res = global_time(1) + global_time(2)
280 global_time(2) = ieor(global_time(1), global_time(2))
281 self%s(1) = ieor(ieor(rotl(global_time(1), 55), global_time(2)),
shiftl(global_time(2), 14))
282 self%s(2) = rotl(global_time(2), 36)
286 pure function rotl(x, k)
result(res)
287 integer(i8),
intent(in) :: x
288 integer,
intent(in) :: k
291 res = ior(
shiftl(x, k), shiftr(x, 64 - k))
Module for pseudo random number generation. The internal pseudo random generator is the xoroshiro128p...
integer(i8) function shiftl(val, shift)
added for nvidia compilers
Parallel random number generator type.
Random number generator type, which contains the state.