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...