0.6.2-dev0
FORCES
FORtran lib for Comp. Env. Sys.
Loading...
Searching...
No Matches
mo_xor4096.f90
Go to the documentation of this file.
1!> \file mo_xor4096.f90
2!> \brief \copybrief mo_xor4096
3!> \details \copydetails mo_xor4096
4
5!> \brief XOR4096-based random number generator
6!> \details This module provides random number generator based on xor4096 algorithm.
7!> \authors Juliane Mai
8!> \date Nov 2011
9!> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
10!! FORCES is released under the LGPLv3+ license \license_note
12
13 ! -----------------------------------------------------------------------------
14 ! The original version of this source code (without multiple streams, optional
15 ! arguments and gaussian distributed RN) is under GNU General Public Licence
16 ! xorgens.c
17 ! Copyright (C) 2004 R. P. Brent.
18 ! This program is free software; you can redistribute it and/or
19 ! modify it under the terms of the GNU General Public License,
20 ! version 2, June 1991, as published by the Free Software Foundation.
21 ! For details see http://www.gnu.org/copyleft/gpl.html .
22
23 ! Author: Richard P. Brent (random@rpbrent.co.uk)
24 ! -----------------------------------------------------------------------------
25
26 use mo_kind, only : i4, i8, sp, dp
27
28 Implicit NONE
29
30 PUBLIC :: n_save_state ! dimension of vector keeping the state of a stream
31
32 PUBLIC :: get_timeseed ! Returns a seed dependend on time
33 PUBLIC :: xor4096 ! Generates uniform distributed random number
34 PUBLIC :: xor4096g ! Generates gaussian distributed random number
35
36 ! ------------------------------------------------------------------
37
38 !> \brief Generate seed for xor4096
39
40 !> \details
41 !! Function which returns a scalar or a vector of integers
42 !! dependent on time.
43 !! This returned values can be used a seed for initializing
44 !! random number generators like xor4096.\n
45 !!
46 !! If the return variable is a vector, only the first entry
47 !! depends on time while the others are just the entry before
48 !! increased by 1000.
49 !!
50 !! \b Example
51 !!
52 !! Results in a scalar seed
53 !! \code{.f90}
54 !! integer(i4) :: seed
55 !! call get_timeseed(seed)
56 !! \endcode
57 !!
58 !! Results in a array of seeds
59 !! \code{.f90}
60 !! integer(i8), dimension(3) :: seed
61 !! call get_timeseed(seed)
62 !! \endcode
63 !! e.g. `seed = (/ 327_i8, 1327_i8, 2327_i8 /)`
64
65
66 !> \param[in] "integer(i4/i8), dimension(:) :: seed" Seed to be generated
67
68
69 !> \author Juliane Mai
70 !> \date Aug 2012
71
72 INTERFACE get_timeseed
73 MODULE PROCEDURE get_timeseed_i4_0d, get_timeseed_i4_1d, &
74 get_timeseed_i8_0d, get_timeseed_i8_1d
75 END INTERFACE get_timeseed
76
77 ! ------------------------------------------------------------------
78
79 !> \brief Uniform XOR4096-based RNG
80
81 !> \details
82 !! Generates a uniform distributed random number based on xor4096 algorithm proposed by
83 !! Brent et.al (2006).\n
84 !! ****************************************************************************************
85 !! The original version of this source code (without multiple streams and
86 !! optional arguments) is under GNU General Public Licence
87 !! xorgens.c
88 !! Copyright (C) 2004 R. P. Brent.
89 !! This program is free software; you can redistribute it and/or
90 !! modify it under the terms of the GNU General Public License,
91 !! version 2, June 1991, as published by the Free Software Foundation.
92 !! For details see http://www.gnu.org/copyleft/gpl.html .
93 !! Author: Richard P. Brent (random@rpbrent.co.uk)
94 !! ****************************************************************************************
95 !! The period of the generator is\n
96 !! (2^4096 - 1)*2^32 for single precision version and
97 !! (2^4096 - 1)*2^64 for double precision version.\n
98 !!
99 !! The generator is based on bitwise XOR compositions of left- and right-shifted numbers.\n
100 !!
101 !! The generator has to be called once with a non-zero seed value which initializes a new
102 !! random number stream. The subsequent calls are with seed=0 which returns the following
103 !! numbers within the beforehand initialized stream. Since the random numbers are based on
104 !! the initial seed, the precison of the seed (sp/dp) determines the precision of the
105 !! returned random number (sp/dp).\n
106 !!
107 !! If one initialize the generator with an array of seeds, one initializes n independent
108 !! streams of random numbers.
109 !! Lets assume that the streams with seed:
110 !! 1_sp is 10, 20, 30 ...\n
111 !! 2_sp is 40, 50, 60 ...\n
112 !! 3_sp is 70, 80, 90 ...\n
113 !!
114 !! What you get is:\n
115 !! 1st call
116 !! \code{.f90}
117 !! call xor( (/ 1_SP, 2_SP, 3_SP /), RN ) --> RN = (/ 10, 40, 70 /)
118 !! \endcode
119 !! 2nd call
120 !! \code{.f90}
121 !! call xor( (/ 0_SP, 0_SP, 0_SP /), RN ) --> RN = (/ 20, 50, 80 /)
122 !! \endcode
123 !! 3rd call
124 !! \code{.f90}
125 !! call xor( (/ 0_SP, 0_SP, 0_SP /), RN ) --> RN = (/ 30, 60, 90 /)
126 !! \endcode
127 !!
128 !! Since after every initialization one looses the old stream of random numbers,
129 !! it might be necessary to switch between different streams. Therefore, one needs
130 !! the optional save_state argument.
131 !! What you get is:
132 !! 1st call of 1st stream
133 !! \code{.f90}
134 !! call xor( 1_SP, RN, save_state=save_stream_1 ) RN = 10
135 !! \endcode
136 !! 2nd call of 1st stream
137 !! \code{.f90}
138 !! call xor( 0_SP, RN, save_state=save_stream_1 ) RN = 20
139 !! \endcode
140 !! 1st call of 2nd stream
141 !! \code{.f90}
142 !! call xor( 2_SP, RN, save_state=save_stream_2 ) RN = 40
143 !! \endcode
144 !! 3rd call of 1st stream
145 !! \code{.f90}
146 !! call xor( 0_SP, RN, save_state=save_stream_1 ) RN = 30
147 !! \endcode
148 !! Note: If you would have called 4 times without optional argument,
149 !! you would have get 50 in the 4th call.
150 !!
151 !! \b Example
152 !!
153 !! I4 seeds are generating I4 or SP random numbers,
154 !! I8 seeds are generating I8 or DP random numbers.
155 !!
156 !! Initializing:
157 !! \code{.f90}
158 !! real(SP) :: RN(3)
159 !! seed = (/ 1_I4, 100_I4, 2_I4 /)
160 !! call xor4096(seed,RN)
161 !! print*, RN --> (/ 0.1_sp, 0.2_sp, 0.6_sp /)
162 !! \endcode
163 !!
164 !! After initializing
165 !! \code{.f90}
166 !! seed = (/ 0_I4, 0_I4, 0_I4 /)
167 !! call xor4096(seed,RN)
168 !! print*, RN --> (/ 0.3_sp, 0.1_sp, 0.5_sp /)
169 !! \endcode
170 !!
171 !! \b Literature
172 !!
173 !! 1. Brent RP. _Some long-period random number generators using shifts and xors_, 2010
174 !! 2. Brent RP. _From Mersenne Primes to Rndom Number Generators_, 2006
175 !! 3. L''Ecuyer P & Simard R. _ACM: TestU01: A C Library for Empirical Testing of
176 !! Random Number Generators_, 2007
177 !!
178 !> \param[in] "integer(i4/i8) :: seed/seed(:)" Value or 1D-array with non-zero seeds for
179 !! initialization or zero for subsequent callsyy
180 !> \param[out] "integer(i4/i8)/real(sp/dp) :: RN/RN(size(seed))"
181 !! uniform distributed random number with
182 !! interval:\n
183 !! - i4: (-2^31,2^31-1)
184 !! - i8: (-2^63,2^63-1)
185 !! - sp: (0.0_sp, 1.0_sp)
186 !! - dp: (0.0_dp, 1.0_dp)
187 !> \param[inout] "integer(i4/i8), dimension(size(seed), n_save_state), opional :: save_state"
188 !! Array carrying state of random number stream
189 !! this should be used if several streams are used, i.e.
190 !! each stream has its own save_state.
191
192 !! \note
193 !! - The dimension of the optional argument can be set using the public module parameter n_save_state.
194 !! - If random numbers are in single precision (sp), one needs seed and save_state in (i4).
195 !! - If random numbers are in double precision (dp), one needs seed and save_state in (i8).
196
197 !> \author Juliane Mai
198 !> \date Nov 2011
199
200 INTERFACE xor4096
201 MODULE PROCEDURE xor4096s_0d, xor4096s_1d, xor4096f_0d, xor4096f_1d, &
202 xor4096l_0d, xor4096l_1d, xor4096d_0d, xor4096d_1d
203 END INTERFACE xor4096
204
205 ! ------------------------------------------------------------------
206
207 !> \brief Gaussian XOR4096-based RNG
208
209 !> \details
210 !! Generates a gaussian distributed random number. First, a uniform distributed random
211 !! number based on xor4096 algorithm is generated. Second, this number is transformed
212 !! using the Polar method of Box-Mueller-transform to calculate the gaussian distributed
213 !! numbers.\n
214 !!
215 !! ****************************************************************************************
216 !! The original version of this source code (without multiple streams,
217 !! optional arguments and gaussian distributed RN) is under GNU General Public Licence
218 !! xorgens.c
219 !! Copyright (C) 2004 R. P. Brent.
220 !! This program is free software; you can redistribute it and/or
221 !! modify it under the terms of the GNU General Public License,
222 !! version 2, June 1991, as published by the Free Software Foundation.
223 !! For details see http://www.gnu.org/copyleft/gpl.html .
224 !!
225 !! Author: Richard P. Brent (random@rpbrent.co.uk)
226 !! ****************************************************************************************
227 !!
228 !! The generator has to be called once with a non-zero seed value which initializes a new
229 !! random number stream. The subsequent calls are with seed=0 which returns the following
230 !! numbers within the beforehand initialized stream. Since the random numbers are based on
231 !! the initial seed, the precison of the seed (sp/dp) determines the precision of the
232 !! returned random number (sp/dp).\n
233 !!
234 !! The returned values are gaussian distributed with mean 0 and variance 1.\n
235 !!
236 !! The polar method of the Box-Mueller transform transforms two uniform distributed
237 !! random numbers \f$u_1\f$ and \f$u_2\f$ into two gaussian distributed random numbers \f$x_1\f$ and \f$x_2\f$.
238 !! First, two uniform numbers a1, a2 distributed between (-1,1) are calculated:\n
239 !! \f[a_1 = 2u_1 - 1\f]
240 !! \f[a_2 = 2u_2 - 1\f]
241 !! Second, \f$q = a_1^2 + a_2^2\f$ is calculated. If (\f$q = 0\f$) or (\f$q > 1\f$) one has to generate
242 !! a new \f$x_1\f$ and \f$x_2\f$, since a divison by q is needed afterwards and q needs to be distributed
243 !! within the unit circle.
244 !! Third,
245 !! \f[p = \sqrt{-2 \frac{\ln{q}}{q}}\f]
246 !! is calculated.
247 !! The numbers \f$z_1\f$ and \f$z_2\f$ with
248 !! \f[z_1 = a_1 p\f]
249 !! \f[z_2 = a_2 p\f]
250 !! are then gaussian distributed with mean 0 and variance 1.
251 !!
252 !! \b Example
253 !!
254 !! See example for xor4096.
255 !!
256 !! \b Literature
257 !!
258 !! 1. Brent RP. _Some long-period random number generators using shifts and xors_, 2010
259 !! 2. Brent RP. _From Mersenne Primes to Rndom Number Generators_, 2006
260 !! 3. L''Ecuyer P & Simard R. _ACM: TestU01: A C Library for Empirical Testing of
261 !! Random Number Generators_, 2007
262 !! 4. http://en.wikipedia.org/wiki/Marsaglia_polar_method
263 !! 5. http://de.wikipedia.org/wiki/Polar-Methode
264 !!
265 !> \param[in] "integer(i4/i8) :: seed/seed(:)" Value or 1D-array with non-zero seeds for
266 !! initialization or zero for subsequent calls
267 !> \param[out] "real(sp/dp) :: RN/RN(size(seed))"
268 !! Gaussian distributed random number with
269 !! interval:\n
270 !! - sp: RN ~ N(0.0_sp, 1.0_sp)
271 !! - dp: RN ~ N(0.0_dp, 1.0_dp)
272 !> \param[inout] "integer(i4/i8), dimension(size(seed),n_save_state), optional :: save_state"
273 !! Array carrying state of random number stream
274 !! this should be used if several streams are used, i.e.
275 !! each stream has its own save_state.
276
277 !> \note
278 !! - The dimension of the optional argument can be set using the public module parameter n_save_state.
279 !! - If random numbers are in single precision (sp), one needs seed and save_state in (i4).
280 !! - If random numbers are in double precision (dp), one needs seed and save_state in (i8).
281
282 !> \author Juliane Mai
283 !> \date Nov 2011
284 !> \date Feb 2013
285 !! - all optionals combined in save_state
286
287 INTERFACE xor4096g
288 MODULE PROCEDURE xor4096gf_0d, xor4096gf_1d, xor4096gd_0d, xor4096gd_1d
289 END INTERFACE xor4096g
290
291 ! ------------------------------------------------------------------
292
293 PRIVATE
294
295 !> Dimension of vector saving the state of a stream
296 integer(i4), parameter :: n_save_state = 132_i4
297
298 ! ------------------------------------------------------------------
299
300CONTAINS
301
302 ! ------------------------------------------------------------------
303
304 subroutine get_timeseed_i4_0d(seed)
305
306 implicit none
307 integer(i4), intent(inout) :: seed
308
309 ! local variables
310 integer(i4), dimension(8) :: time_array
311
312 call date_and_time(values = time_array)
313 seed = &
314 time_array(5) * 3600000_i4 + & ! hour
315 time_array(6) * 60000_i4 + & ! minutes
316 time_array(7) * 1000_i4 + & ! seconds
317 time_array(8) * 1_i4 ! milliseconds
318
319 end subroutine get_timeseed_i4_0d
320
321 subroutine get_timeseed_i4_1d(seed)
322
323 implicit none
324 integer(i4), dimension(:), intent(inout) :: seed
325
326 ! local variables
327 integer(i4), dimension(8) :: time_array
328 integer(i4) :: i
329
330 call date_and_time(values = time_array)
331 seed(1) = &
332 time_array(5) * 3600000_i4 + & ! hour
333 time_array(6) * 60000_i4 + & ! minutes
334 time_array(7) * 1000_i4 + & ! seconds
335 time_array(8) * 1_i4 ! milliseconds
336 do i = 2, size(seed)
337 seed(i) = seed(i - 1) + 1000_i4
338 end do
339
340 end subroutine get_timeseed_i4_1d
341
342 subroutine get_timeseed_i8_0d(seed)
343
344 implicit none
345 integer(i8), intent(inout) :: seed
346
347 ! local variables
348 integer(i4), dimension(8) :: time_array
349
350 call date_and_time(values = time_array)
351 seed = &
352 int(time_array(5), i8) * 3600000_i8 + & ! hour
353 int(time_array(6), i8) * 60000_i8 + & ! minutes
354 int(time_array(7), i8) * 1000_i8 + & ! seconds
355 int(time_array(8), i8) * 1_i8 ! milliseconds
356
357 end subroutine get_timeseed_i8_0d
358
359 subroutine get_timeseed_i8_1d(seed)
360
361 implicit none
362 integer(i8), dimension(:), intent(inout) :: seed
363
364 ! local variables
365 integer(i4), dimension(8) :: time_array
366 integer(i4) :: i
367
368 call date_and_time(values = time_array)
369 seed(1) = &
370 int(time_array(5), i8) * 3600000_i8 + & ! hour
371 int(time_array(6), i8) * 60000_i8 + & ! minutes
372 int(time_array(7), i8) * 1000_i8 + & ! seconds
373 int(time_array(8), i8) * 1_i8 ! milliseconds
374 do i = 2, size(seed)
375 seed(i) = seed(i - 1) + 1000_i8
376 end do
377
378 end subroutine get_timeseed_i8_1d
379
380 ! ------------------------------------------------------------------
381
382 subroutine xor4096s_0d(seed, SingleIntegerRN, save_state)
383 implicit none
384
385 integer(i4), intent(in) :: seed
386 integer(i4), intent(out) :: singleintegerrn
387 integer(i4), optional, dimension(n_save_state), intent(inout) :: save_state
388
389 integer(i4) :: wlen, r, s, a, b, c, d
390
391 integer(i4), save :: w
392 integer(i4), save :: x(0 : 127) ! x(0) ... x(r-1)
393 integer(i4) :: weyl = 1640531527_i4 !Z'61C88647' ! Hexadecimal notation
394 integer(i4) :: t, v, tmp
395 integer(i4), save :: i = -1 ! i<0 indicates first call
396 integer(i4) :: k
397
398 wlen = 32
399 r = 128
400 s = 95
401 a = 17
402 b = 12
403 c = 13
404 d = 15
405
406 if (present(save_state) .and. (seed .eq. 0)) then
407 x(0 : r - 1) = save_state(1 : r)
408 i = save_state(r + 1)
409 w = save_state(r + 2)
410 end if
411
412 If ((i .lt. 0) .or. (seed .ne. 0)) then ! Initialization necessary
413 If (seed .ne. 0) then ! v must be nonzero
414 v = seed
415 else
416 v = not(seed)
417 end if
418
419 do k = wlen, 1, -1 ! Avoid correlations for close seeds
420 ! This recurrence has period of 2^32-1
421 v = ieor(v, ishft(v, 13))
422 v = ieor(v, ishft(v, -17))
423 v = ieor(v, ishft(v, 5))
424 end do
425
426 ! Initialize circular array
427 w = v
428 do k = 0, r - 1
429 ! w = w + weyl
430 if (w < 0_i4) then
431 w = w + weyl
432 else if ((huge(1_i4) - w) > weyl) then
433 w = w + weyl
434 else
435 tmp = -(huge(1_i4) - w - weyl)
436 w = tmp - huge(1_i4) - 2_i4
437 endif
438 v = ieor(v, ishft(v, 13))
439 v = ieor(v, ishft(v, -17))
440 v = ieor(v, ishft(v, 5))
441 x(k) = v + w
442 end do
443
444 ! Discard first 4*r results (Gimeno)
445 i = r - 1
446 do k = 4 * r, 1, -1
447 i = iand(i + 1, r - 1)
448 t = x(i)
449 v = x(iand(i + (r - s), r - 1))
450 t = ieor(t, ishft(t, a))
451 t = ieor(t, ishft(t, -b))
452 v = ieor(v, ishft(v, c))
453 v = ieor(v, ieor(t, ishft(v, -d)))
454 x(i) = v
455 end do
456 end if ! end of initialization
457
458 ! Apart from initialization (above), this is the generator
459 i = iand(i + 1, r - 1)
460 t = x(i)
461 v = x(iand(i + (r - s), r - 1))
462 t = ieor(t, ishft(t, a))
463 t = ieor(t, ishft(t, -b))
464 v = ieor(v, ishft(v, c))
465 v = ieor(v, ieor(t, ishft(v, -d)))
466 x(i) = v
467
468 w = w + weyl
469
470 singleintegerrn = v + w
471
472 if(present(save_state)) then
473 save_state(1 : r) = x(0 : r - 1)
474 save_state(r + 1) = i
475 save_state(r + 2) = w
476 if ((r + 3) <= n_save_state) save_state(r + 3 : n_save_state) = 0
477 end if
478
479 end subroutine xor4096s_0d
480
481 ! -----------------------------------------------------------------------------
482
483 subroutine xor4096s_1d(seed, SingleIntegerRN, save_state)
484 implicit none
485
486 integer(i4), dimension(:), intent(in) :: seed
487 integer(i4), dimension(size(seed, 1)), intent(out) :: singleintegerrn
488 integer(i4), optional, dimension(size(seed, 1), n_save_state), intent(inout) :: save_state
489
490 integer(i4) :: m
491 integer(i4) :: wlen, r, s, a, b, c, d
492 integer(i4) :: weyl = 1640531527_i4 !Z'61C88647' ! Hexadecimal notation
493 integer(i4) :: k, j, tmp
494 integer(i4), dimension(size(seed, 1)) :: t, v
495 integer(i4), dimension(:, :), allocatable, save :: x ! x(0) ... x(r-1)
496 integer(i4), dimension(:), allocatable, save :: i, w ! i<0 indicates first call
497
498 wlen = 32
499 r = 128
500 s = 95
501 a = 17
502 b = 12
503 c = 13
504 d = 15
505
506 m = size(seed, 1)
507
508 if (any(seed .eq. 0_i4) .and. any(seed .ne. 0_i4)) then
509 stop 'xor4096: seeds have to be eigther all 0 or all larger than 0'
510 end if
511
512 if (present(save_state) .and. all(seed .eq. 0_i4)) then
513 if (allocated(x)) then
514 if (size(x, 1) .ne. m) then
515 deallocate(x)
516 deallocate(i)
517 deallocate(w)
518 allocate(i(m))
519 allocate(x(m, 0 : r - 1))
520 allocate(w(m))
521 end if
522 end if
523 if (.not. allocated(x)) then
524 allocate(i(m))
525 allocate(x(m, 0 : r - 1))
526 allocate(w(m))
527 end if
528 x(:, 0 : r - 1) = save_state(:, 1 : r)
529 i(:) = save_state(:, r + 1)
530 w(:) = save_state(:, r + 2)
531 end if
532
533 if(all(seed .ne. 0_i4)) then
534 if (allocated(x)) then
535 deallocate(x)
536 deallocate(i)
537 deallocate(w)
538 end if
539
540 allocate(i(m))
541 i = -1
542 allocate(x(m, 0 : r - 1))
543 allocate(w(m))
544 end if
545
546 Do j = 1, m
547 If ((i(j) .lt. 0) .or. (seed(j) .ne. 0)) then ! Initialization necessary
548 If (seed(j) .ne. 0) then ! v must be nonzero
549 v(j) = seed(j)
550 else
551 v(j) = not(seed(j))
552 end if
553
554 do k = wlen, 1, -1 ! Avoid correlations for close seeds
555 ! This recurrence has period of 2^32-1
556 v(j) = ieor(v(j), ishft(v(j), 13))
557 v(j) = ieor(v(j), ishft(v(j), -17))
558 v(j) = ieor(v(j), ishft(v(j), 5))
559 end do
560
561 ! Initialize circular array
562 w(j) = v(j)
563 do k = 0, r - 1
564 ! w(j) = w(j) + weyl
565 if (w(j) < 0_i4) then
566 w(j) = w(j) + weyl
567 else if ((huge(1_i4) - w(j)) > weyl) then
568 w(j) = w(j) + weyl
569 else
570 tmp = -(huge(1_i4) - w(j) - weyl)
571 w(j) = tmp - huge(1_i4) - 2_i4
572 endif
573 v(j) = ieor(v(j), ishft(v(j), 13))
574 v(j) = ieor(v(j), ishft(v(j), -17))
575 v(j) = ieor(v(j), ishft(v(j), 5))
576 x(j, k) = v(j) + w(j)
577 end do
578
579 ! Discard first 4*r results (Gimeno)
580 i(j) = r - 1
581 do k = 4 * r, 1, -1
582 i(j) = iand(i(j) + 1, r - 1)
583 t(j) = x(j, i(j))
584 v(j) = x(j, iand(i(j) + (r - s), r - 1))
585 t(j) = ieor(t(j), ishft(t(j), a))
586 t(j) = ieor(t(j), ishft(t(j), -b))
587 v(j) = ieor(v(j), ishft(v(j), c))
588 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
589 x(j, i(j)) = v(j)
590 end do
591 end if ! end of initialization
592 end do
593
594 ! Apart from initialization (above), this is the generator
595
596 do j = 1, m
597 i(j) = iand(i(j) + 1, r - 1)
598 t(j) = x(j, i(j))
599 v(j) = x(j, iand(i(j) + (r - s), r - 1))
600 t(j) = ieor(t(j), ishft(t(j), a))
601 t(j) = ieor(t(j), ishft(t(j), -b))
602 v(j) = ieor(v(j), ishft(v(j), c))
603 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
604 x(j, i(j)) = v(j)
605
606 w(j) = w(j) + weyl
607 end do
608
609 singleintegerrn = v + w
610
611 if(present(save_state)) then
612 save_state(:, 1 : r) = x(:, 0 : r - 1)
613 save_state(:, r + 1) = i(:)
614 save_state(:, r + 2) = w(:)
615 if ((r + 3) <= n_save_state) save_state(:, r + 3 : n_save_state) = 0
616 end if
617
618 end subroutine xor4096s_1d
619
620 ! -----------------------------------------------------------------------------
621
622 subroutine xor4096f_0d(seed, SingleRealRN, save_state)
623
624 implicit none
625
626 integer(i4), intent(in) :: seed
627 real(sp), intent(out) :: singlerealrn
628 integer(i4), optional, dimension(n_save_state), intent(inout) :: save_state
629
630 integer(i4) :: wlen, r, s, a, b, c, d
631 integer(i4), save :: w
632 integer(i4), save :: x(0 : 127) ! x(0) ... x(r-1)
633 integer(i4) :: weyl = 1640531527_i4 !Z'61C88647' ! Hexadecimal notation
634 integer(i4) :: t, v, tmp
635 integer(i4), save :: i = -1 ! i<0 indicates first call
636 integer(i4) :: k
637
638 real(sp) :: t24 = 1.0_sp / 16777216.0_sp ! = 0.5^24 = 1/2^24
639
640 !$omp threadprivate(x,i,w)
641 !
642
643 ! produces a 24bit Integer Random Number (0...16777216) and
644 ! scales it afterwards to (0.0,1.0)
645
646 wlen = 32
647 r = 128
648 s = 95
649 a = 17
650 b = 12
651 c = 13
652 d = 15
653
654 if (present(save_state) .and. (seed .eq. 0)) then
655 x(0 : r - 1) = save_state(1 : r)
656 i = save_state(r + 1)
657 w = save_state(r + 2)
658 end if
659
660 If ((i .lt. 0) .or. (seed .ne. 0)) then ! Initialization necessary
661 If (seed .ne. 0) then ! v must be nonzero
662 v = seed
663 else
664 v = not(seed)
665 end if
666
667 do k = wlen, 1, -1 ! Avoid correlations for close seeds
668 ! This recurrence has period of 2^32-1
669 v = ieor(v, ishft(v, 13))
670 v = ieor(v, ishft(v, -17))
671 v = ieor(v, ishft(v, 5))
672 end do
673
674 ! Initialize circular array
675 w = v
676 do k = 0, r - 1
677 ! w = w + weyl
678 if (w < 0_i4) then
679 w = w + weyl
680 else if ((huge(1_i4) - w) > weyl) then
681 w = w + weyl
682 else
683 tmp = -(huge(1_i4) - w - weyl)
684 w = tmp - huge(1_i4) - 2_i4
685 endif
686 v = ieor(v, ishft(v, 13))
687 v = ieor(v, ishft(v, -17))
688 v = ieor(v, ishft(v, 5))
689 x(k) = v + w
690 end do
691
692 ! Discard first 4*r results (Gimeno)
693 i = r - 1
694 do k = 4 * r, 1, -1
695 i = iand(i + 1, r - 1)
696 t = x(i)
697 v = x(iand(i + (r - s), r - 1))
698 t = ieor(t, ishft(t, a))
699 t = ieor(t, ishft(t, -b))
700 v = ieor(v, ishft(v, c))
701 v = ieor(v, ieor(t, ishft(v, -d)))
702 x(i) = v
703 end do
704 end if ! end of initialization
705
706 ! Apart from initialization (above), this is the generator
707 v = 0_i4
708 Do While (v .eq. 0_i4)
709 i = iand(i + 1, r - 1)
710 t = x(i)
711 v = x(iand(i + (r - s), r - 1))
712 t = ieor(t, ishft(t, a))
713 t = ieor(t, ishft(t, -b))
714 v = ieor(v, ishft(v, c))
715 v = ieor(v, ieor(t, ishft(v, -d)))
716 x(i) = v
717 w = w + weyl
718 v = v + w
719 v = ishft(v, -8)
720 End Do
721
722 singlerealrn = t24 * v
723
724 if(present(save_state)) then
725 save_state(1 : r) = x(0 : r - 1)
726 save_state(r + 1) = i
727 save_state(r + 2) = w
728 if ((r + 3) <= n_save_state) save_state(r + 3 : n_save_state) = 0
729 end if
730
731 !
732
733 end subroutine xor4096f_0d
734
735 ! -----------------------------------------------------------------------------
736
737 subroutine xor4096f_1d(seed, SingleRealRN, save_state)
738
739 implicit none
740
741 integer(i4), dimension(:), intent(in) :: seed
742 real(sp), dimension(size(seed)), intent(out) :: singlerealrn
743 integer(i4), optional, dimension(size(seed, 1), n_save_state), intent(inout) :: save_state
744
745 integer(i4) :: m
746 integer(i4) :: wlen, r, s, a, b, c, d
747 integer(i4) :: weyl = 1640531527_i4 !Z'61C88647' = Hexadecimal notation
748 integer(i4) :: k, j, tmp
749 real(sp), save :: t24 = 1.0_sp / 16777216.0_sp ! = 0.5^24 = 1/2^24
750 integer(i4), dimension(size(seed)) :: t, v
751 integer(i4), dimension(:, :), allocatable, save :: x ! x(0) ... x(r-1)
752 integer(i4), dimension(:), allocatable, save :: i, w ! i<0 indicates first call
753
754 ! produces a 24bit Integer Random Number (0...16777216) and
755 ! scales it afterwards to (0.0,1.0)
756
757 !$omp threadprivate(x,i,w)
758
759 wlen = 32
760 r = 128
761 s = 95
762 a = 17
763 b = 12
764 c = 13
765 d = 15
766
767 m = size(seed, 1)
768
769 if (any(seed .eq. 0_i4) .and. any(seed .ne. 0_i4)) then
770 stop 'xor4096: seeds have to be eigther all 0 or all larger than 0'
771 end if
772
773 if (present(save_state) .and. all(seed .eq. 0_i4)) then
774 if (allocated(x)) then
775 if (size(x, 1) .ne. m) then
776 deallocate(x)
777 deallocate(i)
778 deallocate(w)
779 allocate(i(m))
780 allocate(x(m, 0 : r - 1))
781 allocate(w(m))
782 end if
783 end if
784 if (.not. allocated(x)) then
785 allocate(i(m))
786 allocate(x(m, 0 : r - 1))
787 allocate(w(m))
788 end if
789 x(:, 0 : r - 1) = save_state(:, 1 : r)
790 i(:) = save_state(:, r + 1)
791 w(:) = save_state(:, r + 2)
792 end if
793
794 if(all(seed .ne. 0_i4)) then
795 if (allocated(x)) then
796 deallocate(x)
797 deallocate(i)
798 deallocate(w)
799 end if
800
801 allocate(i(m))
802 i = -1
803 allocate(x(m, 0 : r - 1))
804 allocate(w(m))
805 end if
806
807 Do j = 1, m !Loop over every stream
808 If ((i(j) .lt. 0) .or. (seed(j) .ne. 0)) then ! Initialization necessary
809 If (seed(j) .ne. 0) then ! v must be nonzero
810 v(j) = seed(j)
811 else
812 v(j) = not(seed(j))
813 end if
814
815 do k = wlen, 1, -1 ! Avoid correlations for close seeds
816 ! This recurrence has period of 2^32-1
817 v(j) = ieor(v(j), ishft(v(j), 13))
818 v(j) = ieor(v(j), ishft(v(j), -17))
819 v(j) = ieor(v(j), ishft(v(j), 5))
820 end do
821
822 ! Initialize circular array
823 w(j) = v(j)
824 do k = 0, r - 1
825 ! w(j) = w(j) + weyl
826 if (w(j) < 0_i4) then
827 w(j) = w(j) + weyl
828 else if ((huge(1_i4) - w(j)) > weyl) then
829 w(j) = w(j) + weyl
830 else
831 tmp = -(huge(1_i4) - w(j) - weyl)
832 w(j) = tmp - huge(1_i4) - 2_i4
833 endif
834 v(j) = ieor(v(j), ishft(v(j), 13))
835 v(j) = ieor(v(j), ishft(v(j), -17))
836 v(j) = ieor(v(j), ishft(v(j), 5))
837 x(j, k) = v(j) + w(j)
838 end do
839
840 ! Discard first 4*r results (Gimeno)
841 i(j) = r - 1
842 do k = 4 * r, 1, -1
843 i(j) = iand(i(j) + 1, r - 1)
844 t(j) = x(j, i(j))
845 v(j) = x(j, iand(i(j) + (r - s), r - 1))
846 t(j) = ieor(t(j), ishft(t(j), a))
847 t(j) = ieor(t(j), ishft(t(j), -b))
848 v(j) = ieor(v(j), ishft(v(j), c))
849 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
850 x(j, i(j)) = v(j)
851 end do
852 end if ! end of initialization
853 end do
854
855 ! Apart from initialization (above), this is the generator
856 v = 0_i4
857 Do j = 1, m
858 Do While (v(j) .eq. 0_i4)
859 i(j) = iand(i(j) + 1, r - 1)
860 t(j) = x(j, i(j))
861 v(j) = x(j, iand(i(j) + (r - s), r - 1))
862 t(j) = ieor(t(j), ishft(t(j), a))
863 t(j) = ieor(t(j), ishft(t(j), -b))
864 v(j) = ieor(v(j), ishft(v(j), c))
865 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
866 x(j, i(j)) = v(j)
867 w(j) = w(j) + weyl
868 v(j) = v(j) + w(j)
869 v(j) = ishft(v(j), -8)
870 End Do
871 End Do
872
873 singlerealrn = t24 * v
874
875 if(present(save_state)) then
876 save_state(:, 1 : r) = x(:, 0 : r - 1)
877 save_state(:, r + 1) = i(:)
878 save_state(:, r + 2) = w(:)
879 if ((r + 3) <= n_save_state) save_state(:, r + 3 : n_save_state) = 0
880 end if
881
882 end subroutine xor4096f_1d
883
884 ! -----------------------------------------------------------------------------
885
886 subroutine xor4096l_0d(seed, DoubleIntegerRN, save_state)
887
888 implicit none
889
890 integer(i8), intent(in) :: seed
891 integer(i8), intent(out) :: doubleintegerrn
892 integer(i8), optional, dimension(n_save_state), intent(inout) :: save_state
893
894 integer(i8) :: wlen, r, s, a, b, c, d
895 integer(i8), save :: w
896 integer(i8), save :: x(0 : 63) ! x(0) ... x(r-1)
897 integer(i8) :: weyl = 7046029254386353131_i8
898 integer(i8) :: t, v, tmp
899 integer(i8), save :: i = -1 ! i<0 indicates first call
900 integer(i8) :: k
901
902 !$omp threadprivate(x,i,w)
903
904 wlen = 64_i8
905 r = 64_i8
906 s = 53_i8
907 a = 33_i8
908 b = 26_i8
909 c = 27_i8
910 d = 29_i8
911
912 if (present(save_state) .and. (seed .eq. 0_i8)) then
913 x(0 : r - 1) = save_state(1 : r)
914 i = save_state(r + 1)
915 w = save_state(r + 2)
916 end if
917
918 If ((i .lt. 0) .or. (seed .ne. 0)) then ! Initialization necessary
919 If (seed .ne. 0) then ! v must be nonzero
920 v = seed
921 else
922 v = not(seed)
923 end if
924
925 do k = wlen, 1, -1 ! Avoid correlations for close seeds
926 ! This recurrence has period of 2^64-1
927 v = ieor(v, ishft(v, 7))
928 v = ieor(v, ishft(v, -9))
929 end do
930
931 ! Initialize circular array
932 w = v
933 do k = 0, r - 1
934 ! w = w + weyl
935 if (w < 0_i8) then
936 w = w + weyl
937 else if ((huge(1_i8) - w) > weyl) then
938 w = w + weyl
939 else
940 tmp = -(huge(1_i8) - w - weyl)
941 w = tmp - huge(1_i8) - 2_i8
942 endif
943 v = ieor(v, ishft(v, 7))
944 v = ieor(v, ishft(v, -9))
945 x(k) = v + w
946 end do
947
948 ! Discard first 4*r results (Gimeno)
949 i = r - 1
950 do k = 4 * r, 1, -1
951 i = iand(i + 1, r - 1)
952 t = x(i)
953 v = x(iand(i + (r - s), r - 1))
954 t = ieor(t, ishft(t, a))
955 t = ieor(t, ishft(t, -b))
956 v = ieor(v, ishft(v, c))
957 v = ieor(v, ieor(t, ishft(v, -d)))
958 x(i) = v
959 end do
960 end if ! end of initialization
961
962 ! Apart from initialization (above), this is the generator
963 i = iand(i + 1, r - 1)
964 t = x(i)
965 v = x(iand(i + (r - s), r - 1))
966 t = ieor(t, ishft(t, a))
967 t = ieor(t, ishft(t, -b))
968 v = ieor(v, ishft(v, c))
969 v = ieor(v, ieor(t, ishft(v, -d)))
970 x(i) = v
971
972 w = w + weyl
973
974 doubleintegerrn = v + w
975
976 if(present(save_state)) then
977 save_state(1 : r) = x(0 : r - 1)
978 save_state(r + 1) = i
979 save_state(r + 2) = w
980 if ((r + 3) <= n_save_state) save_state(r + 3 : n_save_state) = 0
981 end if
982
983 end subroutine xor4096l_0d
984
985 ! -----------------------------------------------------------------------------
986
987 subroutine xor4096l_1d(seed, DoubleIntegerRN, save_state)
988
989 implicit none
990
991 integer(i8), dimension(:), intent(in) :: seed
992 integer(i8), dimension(size(seed, 1)), intent(out) :: doubleintegerrn
993 integer(i8), optional, dimension(size(seed, 1), n_save_state), intent(inout) :: save_state
994
995 integer(i4) :: m
996 integer(i8) :: wlen, r, s, a, b, c, d
997 integer(i8) :: weyl = 7046029254386353131_i8
998 integer(i8) :: k, j, tmp
999 integer(i8), dimension(size(seed)) :: t, v
1000 integer(i8), dimension(:, :), allocatable, save :: x ! x(0) ... x(r-1)
1001 integer(i8), dimension(:), allocatable, save :: i, w ! i<0 indicates first call
1002
1003 !$omp threadprivate(x,i,w)
1004
1005 wlen = 64_i8
1006 r = 64_i8
1007 s = 53_i8
1008 a = 33_i8
1009 b = 26_i8
1010 c = 27_i8
1011 d = 29_i8
1012
1013 m = size(seed, 1)
1014
1015 if (any(seed .eq. 0_i8) .and. any(seed .ne. 0_i8)) then
1016 stop 'xor4096: seeds have to be eigther all 0 or all larger than 0'
1017 end if
1018
1019 if (present(save_state) .and. all(seed .eq. 0_i4)) then
1020 if (allocated(x)) then
1021 if (size(x, 1) .ne. m) then
1022 deallocate(x)
1023 deallocate(i)
1024 deallocate(w)
1025 allocate(i(m))
1026 allocate(x(m, 0 : r - 1))
1027 allocate(w(m))
1028 end if
1029 end if
1030 if (.not. allocated(x)) then
1031 allocate(i(m))
1032 allocate(x(m, 0 : r - 1))
1033 allocate(w(m))
1034 end if
1035 x(:, 0 : r - 1) = save_state(:, 1 : r)
1036 i(:) = save_state(:, r + 1)
1037 w(:) = save_state(:, r + 2)
1038 end if
1039
1040 if(all(seed .ne. 0_i4)) then
1041 if (allocated(x)) then
1042 deallocate(x)
1043 deallocate(i)
1044 deallocate(w)
1045 end if
1046
1047 allocate(i(m))
1048 i = -1
1049 allocate(x(m, 0 : r - 1))
1050 allocate(w(m))
1051 end if
1052
1053 Do j = 1, m
1054 If ((i(j) .lt. 0) .or. (seed(j) .ne. 0)) then ! Initialization necessary
1055 If (seed(j) .ne. 0) then ! v must be nonzero
1056 v(j) = seed(j)
1057 else
1058 v(j) = not(seed(j))
1059 end if
1060
1061 do k = wlen, 1, -1 ! Avoid correlations for close seeds
1062 ! This recurrence has period of 2^64-1
1063 v(j) = ieor(v(j), ishft(v(j), 7))
1064 v(j) = ieor(v(j), ishft(v(j), -9))
1065 end do
1066
1067 ! Initialize circular array
1068 w(j) = v(j)
1069 do k = 0, r - 1
1070 ! w(j) = w(j) + weyl
1071 if (w(j) < 0_i8) then
1072 w(j) = w(j) + weyl
1073 else if ((huge(1_i8) - w(j)) > weyl) then
1074 w(j) = w(j) + weyl
1075 else
1076 tmp = -(huge(1_i8) - w(j) - weyl)
1077 w(j) = tmp - huge(1_i8) - 2_i8
1078 endif
1079 v(j) = ieor(v(j), ishft(v(j), 7))
1080 v(j) = ieor(v(j), ishft(v(j), -9))
1081 x(j, k) = v(j) + w(j)
1082 end do
1083
1084 ! Discard first 4*r results (Gimeno)
1085 i(j) = r - 1
1086 do k = 4 * r, 1, -1
1087 i(j) = iand(i(j) + 1, r - 1)
1088 t(j) = x(j, i(j))
1089 v(j) = x(j, iand(i(j) + (r - s), r - 1))
1090 t(j) = ieor(t(j), ishft(t(j), a))
1091 t(j) = ieor(t(j), ishft(t(j), -b))
1092 v(j) = ieor(v(j), ishft(v(j), c))
1093 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
1094 x(j, i(j)) = v(j)
1095 end do
1096 end if ! end of initialization
1097 end do
1098
1099 ! Apart from initialization (above), this is the generator
1100 do j = 1, m
1101 i(j) = iand(i(j) + 1, r - 1)
1102 t(j) = x(j, i(j))
1103 v(j) = x(j, iand(i(j) + (r - s), r - 1))
1104 t(j) = ieor(t(j), ishft(t(j), a))
1105 t(j) = ieor(t(j), ishft(t(j), -b))
1106 v(j) = ieor(v(j), ishft(v(j), c))
1107 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
1108 x(j, i(j)) = v(j)
1109
1110 w(j) = w(j) + weyl
1111 end do
1112
1113 doubleintegerrn = v + w
1114
1115 if(present(save_state)) then
1116 save_state(:, 1 : r) = x(:, 0 : r - 1)
1117 save_state(:, r + 1) = i(:)
1118 save_state(:, r + 2) = w(:)
1119 if ((r + 3) <= n_save_state) save_state(:, r + 3 : n_save_state) = 0
1120 end if
1121
1122 end subroutine xor4096l_1d
1123
1124 ! -----------------------------------------------------------------------------
1125
1126 subroutine xor4096d_0d(seed, DoubleRealRN, save_state)
1127
1128 implicit none
1129
1130 integer(i8), intent(in) :: seed
1131 real(dp), intent(out) :: doublerealrn
1132 integer(i8), optional, dimension(n_save_state), intent(inout) :: save_state
1133
1134 integer(i8) :: wlen, r, s, a, b, c, d
1135
1136 integer(i8), save :: w
1137 integer(i8), save :: x(0 : 63) ! x(0) ... x(r-1)
1138 integer(i8) :: weyl = 7046029254386353131_i8
1139 integer(i8) :: t, v, tmp
1140 integer(i8), save :: i = -1 ! i<0 indicates first call
1141 integer(i8) :: k
1142
1143 real(dp) :: t53 = 1.0_dp / 9007199254740992.0_dp ! = 0.5^53 = 1/2^53
1144
1145 !$omp threadprivate(x,i,w)
1146
1147 ! produces a 53bit Integer Random Number (0...9 007 199 254 740 992) and
1148 ! scales it afterwards to (0.0,1.0)
1149
1150 wlen = 64_i8
1151 r = 64_i8
1152 s = 53_i8
1153 a = 33_i8
1154 b = 26_i8
1155 c = 27_i8
1156 d = 29_i8
1157
1158 if (present(save_state) .and. (seed .eq. 0_i8)) then
1159 x(0 : r - 1) = save_state(1 : r)
1160 i = save_state(r + 1)
1161 w = save_state(r + 2)
1162 end if
1163
1164 If ((i .lt. 0) .or. (seed .ne. 0)) then ! Initialization necessary
1165 If (seed .ne. 0) then ! v must be nonzero
1166 v = seed
1167 else
1168 v = not(seed)
1169 end if
1170
1171 do k = wlen, 1, -1 ! Avoid correlations for close seeds
1172 ! This recurrence has period of 2^64-1
1173 v = ieor(v, ishft(v, 7))
1174 v = ieor(v, ishft(v, -9))
1175 end do
1176
1177 ! Initialize circular array
1178 w = v
1179 do k = 0, r - 1
1180 ! w = w + weyl
1181 if (w < 0_i8) then
1182 w = w + weyl
1183 else if ((huge(1_i8) - w) > weyl) then
1184 w = w + weyl
1185 else
1186 tmp = -(huge(1_i8) - w - weyl)
1187 w = tmp - huge(1_i8) - 2_i8
1188 endif
1189 v = ieor(v, ishft(v, 7))
1190 v = ieor(v, ishft(v, -9))
1191 x(k) = v + w
1192 end do
1193
1194 ! Discard first 4*r results (Gimeno)
1195 i = r - 1
1196 do k = 4 * r, 1, -1
1197 i = iand(i + 1, r - 1)
1198 t = x(i)
1199 v = x(iand(i + (r - s), r - 1))
1200 t = ieor(t, ishft(t, a))
1201 t = ieor(t, ishft(t, -b))
1202 v = ieor(v, ishft(v, c))
1203 v = ieor(v, ieor(t, ishft(v, -d)))
1204 x(i) = v
1205 end do
1206 end if ! end of initialization
1207
1208 ! Apart from initialization (above), this is the generator
1209 v = 0_i8
1210 Do While (v .eq. 0_i8)
1211 i = iand(i + 1, r - 1)
1212 t = x(i)
1213 v = x(iand(i + (r - s), r - 1))
1214 t = ieor(t, ishft(t, a))
1215 t = ieor(t, ishft(t, -b))
1216 v = ieor(v, ishft(v, c))
1217 v = ieor(v, ieor(t, ishft(v, -d)))
1218 x(i) = v
1219 w = w + weyl
1220 v = v + w
1221 v = ishft(v, -11)
1222 End Do
1223
1224 doublerealrn = t53 * v
1225
1226 if(present(save_state)) then
1227 save_state(1 : r) = x(0 : r - 1)
1228 save_state(r + 1) = i
1229 save_state(r + 2) = w
1230 if ((r + 3) <= n_save_state) save_state(r + 3 : n_save_state) = 0
1231 end if
1232
1233 end subroutine xor4096d_0d
1234
1235 ! -----------------------------------------------------------------------------
1236
1237 subroutine xor4096d_1d(seed, DoubleRealRN, save_state)
1238
1239 implicit none
1240
1241 integer(i8), dimension(:), intent(in) :: seed
1242 real(dp), dimension(size(seed, 1)), intent(out) :: doublerealrn
1243 integer(i8), optional, dimension(size(seed, 1), n_save_state), intent(inout) :: save_state
1244
1245 integer(i4) :: m
1246 integer(i8) :: wlen, r, s, a, b, c, d
1247 integer(i8) :: weyl = 7046029254386353131_i8
1248 real(dp) :: t53 = 1.0_dp / 9007199254740992.0_dp ! = 0.5^53 = 1/2^53
1249 integer(i8) :: k, j, tmp
1250 integer(i8), dimension(size(seed)) :: t, v
1251 integer(i8), dimension(:, :), allocatable, save :: x ! x(0) ... x(r-1)
1252 integer(i8), dimension(:), allocatable, save :: w
1253 integer(i8), dimension(:), allocatable, save :: i ! i<0 indicates first call
1254
1255 !$omp threadprivate(x,i,w)
1256
1257 ! produces a 53bit Integer Random Number (0...9 007 199 254 740 992) and
1258 ! scales it afterwards to (0.0,1.0)
1259
1260 wlen = 64_i8
1261 r = 64_i8
1262 s = 53_i8
1263 a = 33_i8
1264 b = 26_i8
1265 c = 27_i8
1266 d = 29_i8
1267
1268 m = size(seed, 1)
1269
1270 if (any(seed .eq. 0_i8) .and. any(seed .ne. 0_i8)) then
1271 stop 'xor4096: seeds have to be eigther all 0 or all larger than 0'
1272 end if
1273
1274 if (present(save_state) .and. all(seed .eq. 0_i4)) then
1275 if (allocated(x)) then
1276 if (size(x, 1) .ne. m) then
1277 deallocate(x)
1278 deallocate(i)
1279 deallocate(w)
1280 allocate(i(m))
1281 allocate(x(m, 0 : r - 1))
1282 allocate(w(m))
1283 end if
1284 end if
1285 if (.not. allocated(x)) then
1286 allocate(i(m))
1287 allocate(x(m, 0 : r - 1))
1288 allocate(w(m))
1289 end if
1290 x(:, 0 : r - 1) = save_state(:, 1 : r)
1291 i(:) = save_state(:, r + 1)
1292 w(:) = save_state(:, r + 2)
1293 end if
1294
1295 if(all(seed .ne. 0_i4)) then
1296 if (allocated(x)) then
1297 deallocate(x)
1298 deallocate(i)
1299 deallocate(w)
1300 end if
1301
1302 allocate(i(m))
1303 i = -1
1304 allocate(x(m, 0 : r - 1))
1305 allocate(w(m))
1306 end if
1307
1308 Do j = 1, m
1309 If ((i(j) .lt. 0) .or. (seed(j) .ne. 0)) then ! Initialization necessary
1310 If (seed(j) .ne. 0) then ! v must be nonzero
1311 v(j) = seed(j)
1312 else
1313 v(j) = not(seed(j))
1314 end if
1315
1316 do k = wlen, 1, -1 ! Avoid correlations for close seeds
1317 ! This recurrence has period of 2^64-1
1318 v(j) = ieor(v(j), ishft(v(j), 7))
1319 v(j) = ieor(v(j), ishft(v(j), -9))
1320 end do
1321
1322 ! Initialize circular array
1323 w(j) = v(j)
1324 do k = 0, r - 1
1325 ! w(j) = w(j) + weyl
1326 if (w(j) < 0_i8) then
1327 w(j) = w(j) + weyl
1328 else if ((huge(1_i8) - w(j)) > weyl) then
1329 w(j) = w(j) + weyl
1330 else
1331 tmp = -(huge(1_i8) - w(j) - weyl)
1332 w(j) = tmp - huge(1_i8) - 2_i8
1333 endif
1334 v(j) = ieor(v(j), ishft(v(j), 7))
1335 v(j) = ieor(v(j), ishft(v(j), -9))
1336 x(j, k) = v(j) + w(j)
1337 end do
1338
1339 ! Discard first 4*r results (Gimeno)
1340 i(j) = r - 1
1341 do k = 4 * r, 1, -1
1342 i(j) = iand(i(j) + 1, r - 1)
1343 t(j) = x(j, i(j))
1344 v(j) = x(j, iand(i(j) + (r - s), r - 1))
1345 t(j) = ieor(t(j), ishft(t(j), a))
1346 t(j) = ieor(t(j), ishft(t(j), -b))
1347 v(j) = ieor(v(j), ishft(v(j), c))
1348 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
1349 x(j, i(j)) = v(j)
1350 end do
1351 end if ! end of initialization
1352 end do
1353
1354 ! Apart from initialization (above), this is the generator
1355 v = 0_i8
1356 Do j = 1, m
1357 Do While (v(j) .eq. 0_i8)
1358 i(j) = iand(i(j) + 1, r - 1)
1359 t(j) = x(j, i(j))
1360 v(j) = x(j, iand(i(j) + (r - s), r - 1))
1361 t(j) = ieor(t(j), ishft(t(j), a))
1362 t(j) = ieor(t(j), ishft(t(j), -b))
1363 v(j) = ieor(v(j), ishft(v(j), c))
1364 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
1365 x(j, i(j)) = v(j)
1366 w(j) = w(j) + weyl
1367 v(j) = v(j) + w(j)
1368 v(j) = ishft(v(j), -11)
1369 End Do
1370 End Do
1371
1372 doublerealrn = t53 * v
1373
1374 if(present(save_state)) then
1375 save_state(:, 1 : r) = x(:, 0 : r - 1)
1376 save_state(:, r + 1) = i(:)
1377 save_state(:, r + 2) = w(:)
1378 if ((r + 3) <= n_save_state) save_state(:, r + 3 : n_save_state) = 0
1379 end if
1380
1381 end subroutine xor4096d_1d
1382
1383 ! ------------------------------------------------------------------
1384
1385 subroutine xor4096gf_0d(seed, SingleRealRN, save_state)
1386
1387 implicit none
1388
1389 integer(i4), intent(in) :: seed
1390 real(sp), intent(out) :: singlerealrn
1391 integer(i4), optional, dimension(n_save_state), intent(inout) :: save_state
1392
1393 integer(i4) :: wlen, r, s, a, b, c, d
1394 integer(i4), save :: w
1395 integer(i4), save :: x(0 : 127) ! x(0) ... x(r-1)
1396 integer(i4) :: weyl = 1640531527_i4
1397 integer(i4) :: t, v, tmp
1398 integer(i4), save :: i = -1 ! i<0 indicates first call
1399 integer(i4) :: k
1400 real(sp) :: t24 = 1.0_sp / 16777216.0_sp ! = 0.5^24 = 1/2^24
1401
1402 real(sp) :: rn1, rn2 ! uniform random numbers
1403 real(sp) :: x1, x2, y1, ww ! for Box-Mueller transform
1404 integer(i4), save :: flag = 1 ! if Flag = 1 return y1 else return y2
1405 real(sp), save :: y2
1406
1407 !$omp threadprivate(x,i,w,y2,flag)
1408
1409 ! produces a 24bit Integer Random Number (0...16777216) and
1410 ! scales it afterwards to (0.0,1.0)
1411 ! transform using polar-method
1412
1413 wlen = 32
1414 r = 128
1415 s = 95
1416 a = 17
1417 b = 12
1418 c = 13
1419 d = 15
1420
1421 if(present(save_state) .and. (seed .eq. 0)) then
1422 x(0 : r - 1) = save_state(1 : r)
1423 i = save_state(r + 1)
1424 w = save_state(r + 2)
1425 flag = save_state(r + 3)
1426 y2 = transfer(save_state(r + 4), 1.0_sp)
1427 end if
1428
1429 If ((i .lt. 0) .or. (seed .ne. 0)) then ! Initialization necessary
1430 If (seed .ne. 0) then ! v must be nonzero
1431 v = seed
1432 else
1433 v = not(seed)
1434 end if
1435
1436 do k = wlen, 1, -1 ! Avoid correlations for close seeds
1437 ! This recurrence has period of 2^32-1
1438 v = ieor(v, ishft(v, 13))
1439 v = ieor(v, ishft(v, -17))
1440 v = ieor(v, ishft(v, 5))
1441 end do
1442
1443 ! Initialize circular array
1444 w = v
1445 do k = 0, r - 1
1446 ! w = w + weyl
1447 if (w < 0_i4) then
1448 w = w + weyl
1449 else if ((huge(1_i4) - w) > weyl) then
1450 w = w + weyl
1451 else
1452 tmp = -(huge(1_i4) - w - weyl)
1453 w = tmp - huge(1_i4) - 2_i4
1454 endif
1455 v = ieor(v, ishft(v, 13))
1456 v = ieor(v, ishft(v, -17))
1457 v = ieor(v, ishft(v, 5))
1458 x(k) = v + w
1459 end do
1460
1461 ! Discard first 4*r results (Gimeno)
1462 i = r - 1
1463 do k = 4 * r, 1, -1
1464 i = iand(i + 1, r - 1)
1465 t = x(i)
1466 v = x(iand(i + (r - s), r - 1))
1467 t = ieor(t, ishft(t, a))
1468 t = ieor(t, ishft(t, -b))
1469 v = ieor(v, ishft(v, c))
1470 v = ieor(v, ieor(t, ishft(v, -d)))
1471 x(i) = v
1472 end do
1473 flag = 1
1474 end if ! end of initialization
1475
1476 If (flag .eq. 1) then
1477 ! Polar method of Box-Mueller-transform to generate Gaussian distributed random number
1478 ww = 1.0_sp
1479 do while (ww .ge. 1.0_sp)
1480
1481 ! Apart from initialization (above), this is the generator
1482 v = 0_i4
1483 Do While (v .eq. 0_i4)
1484 i = iand(i + 1, r - 1)
1485 t = x(i)
1486 v = x(iand(i + (r - s), r - 1))
1487 t = ieor(t, ishft(t, a))
1488 t = ieor(t, ishft(t, -b))
1489 v = ieor(v, ishft(v, c))
1490 v = ieor(v, ieor(t, ishft(v, -d)))
1491 x(i) = v
1492 w = w + weyl
1493 v = v + w
1494 v = ishft(v, -8)
1495 End Do
1496
1497 rn1 = t24 * v
1498
1499 v = 0_i4
1500 Do While (v .eq. 0_i4)
1501 i = iand(i + 1, r - 1)
1502 t = x(i)
1503 v = x(iand(i + (r - s), r - 1))
1504 t = ieor(t, ishft(t, a))
1505 t = ieor(t, ishft(t, -b))
1506 v = ieor(v, ishft(v, c))
1507 v = ieor(v, ieor(t, ishft(v, -d)))
1508 x(i) = v
1509 w = w + weyl
1510 v = v + w
1511 v = ishft(v, -8)
1512 End Do
1513
1514 rn2 = t24 * v
1515
1516 x1 = 2.0_sp * rn1 - 1.0_sp
1517 x2 = 2.0_sp * rn2 - 1.0_sp
1518
1519 ww = x1 * x1 + x2 * x2
1520 end do ! end of polar method
1521
1522 ww = sqrt((-2.0_sp * log(ww)) / ww)
1523 y1 = x1 * ww
1524 y2 = x2 * ww
1525
1526 end if ! Only if Flag = 1
1527
1528 If (flag .eq. 1) then
1529 flag = 2
1530 singlerealrn = y1
1531 else
1532 flag = 1
1533 singlerealrn = y2
1534 end if
1535
1536 if(present(save_state)) then
1537 save_state(1 : r) = x(0 : r - 1)
1538 save_state(r + 1) = i
1539 save_state(r + 2) = w
1540 save_state(r + 3) = flag
1541 save_state(r + 4) = transfer(y2, 1_i4)
1542 if ((r + 5) <= n_save_state) save_state(r + 5 : n_save_state) = 0
1543 end if
1544
1545 end subroutine xor4096gf_0d
1546
1547 ! -----------------------------------------------------------------------------
1548
1549 subroutine xor4096gf_1d(seed, SingleRealRN, save_state)
1550
1551 implicit none
1552
1553 integer(i4), dimension(:), intent(in) :: seed
1554 real(sp), dimension(size(seed)), intent(out) :: singlerealrn
1555 integer(i4), optional, dimension(size(seed), n_save_state), intent(inout) :: save_state
1556
1557 integer(i4) :: m
1558 integer(i4) :: wlen, r, s, a, b, c, d
1559 integer(i4) :: weyl = 1640531527_i4
1560 integer(i4) :: k, j, tmp
1561 real(sp) :: t24 = 1.0_sp / 16777216.0_sp ! = 0.5^24 = 1/2^24
1562 integer(i4), dimension(size(seed)) :: t, v
1563 integer(i4), dimension(:, :), allocatable, save :: x ! x(0) ... x(r-1)
1564 integer(i4), dimension(:), allocatable, save :: i, w ! i<0 indicates first call
1565
1566 real(sp), dimension(size(seed)) :: rn1, rn2 ! uniform random numbers
1567 real(sp), dimension(size(seed)) :: x1, x2, y1, ww ! for Box-Mueller transform
1568 real(sp), dimension(:), allocatable, save :: y2
1569 integer(i4), dimension(:), allocatable, save :: flag ! if Flag = 1 return y1 else return y2
1570
1571 !$omp threadprivate(x,i,w,y2,flag)
1572
1573 ! produces a 24bit Integer Random Number (0...16777216) and
1574 ! scales it afterwards to (0.0,1.0)
1575 ! transform using polar-method
1576
1577 wlen = 32
1578 r = 128
1579 s = 95
1580 a = 17
1581 b = 12
1582 c = 13
1583 d = 15
1584
1585 m = size(seed, 1)
1586
1587 if (any(seed .eq. 0_i4) .and. any(seed .ne. 0_i4)) then
1588 stop 'xor4096g: seeds have to be eigther all 0 or all larger than 0'
1589 end if
1590
1591 if (present(save_state) .and. all(seed .eq. 0_i4)) then
1592 if (allocated(x)) then
1593 if (size(x, 1) .ne. m) then
1594 deallocate(x)
1595 deallocate(i)
1596 deallocate(w)
1597 deallocate(flag)
1598 deallocate(y2)
1599 allocate(i(m))
1600 allocate(x(m, 0 : r - 1))
1601 allocate(w(m))
1602 allocate(flag(m))
1603 allocate(y2(m))
1604 end if
1605 end if
1606 if (.not. allocated(x)) then
1607 allocate(i(m))
1608 allocate(x(m, 0 : r - 1))
1609 allocate(w(m))
1610 allocate(flag(m))
1611 allocate(y2(m))
1612 end if
1613 x(:, 0 : r - 1) = save_state(:, 1 : r)
1614 i(:) = save_state(:, r + 1)
1615 w(:) = save_state(:, r + 2)
1616 flag(:) = save_state(:, r + 3)
1617 do j = 1, m
1618 y2(j) = transfer(save_state(j, r + 4), 1.0_sp)
1619 end do
1620 end if
1621
1622 if(all(seed .ne. 0_i4)) then
1623 if (allocated(x)) then
1624 deallocate(x)
1625 deallocate(i)
1626 deallocate(w)
1627 deallocate(flag)
1628 deallocate(y2)
1629 end if
1630
1631 allocate(i(m))
1632 i = -1
1633 allocate(x(m, 0 : r - 1))
1634 allocate(w(m))
1635 allocate(flag(m))
1636 flag = 1
1637 allocate(y2(m))
1638 end if
1639
1640 Do j = 1, m !Loop over every stream
1641 If ((i(j) .lt. 0) .or. (seed(j) .ne. 0)) then ! Initialization necessary
1642 If (seed(j) .ne. 0) then ! v must be nonzero
1643 v(j) = seed(j)
1644 else
1645 v(j) = not(seed(j))
1646 end if
1647
1648 do k = wlen, 1, -1 ! Avoid correlations for close seeds
1649 ! This recurrence has period of 2^32-1
1650 v(j) = ieor(v(j), ishft(v(j), 13))
1651 v(j) = ieor(v(j), ishft(v(j), -17))
1652 v(j) = ieor(v(j), ishft(v(j), 5))
1653 end do
1654
1655 ! Initialize circular array
1656 w(j) = v(j)
1657 do k = 0, r - 1
1658 ! w(j) = w(j) + weyl
1659 if (w(j) < 0_i4) then
1660 w(j) = w(j) + weyl
1661 else if ((huge(1_i4) - w(j)) > weyl) then
1662 w(j) = w(j) + weyl
1663 else
1664 tmp = -(huge(1_i4) - w(j) - weyl)
1665 w(j) = tmp - huge(1_i4) - 2_i4
1666 endif
1667 v(j) = ieor(v(j), ishft(v(j), 13))
1668 v(j) = ieor(v(j), ishft(v(j), -17))
1669 v(j) = ieor(v(j), ishft(v(j), 5))
1670 x(j, k) = v(j) + w(j)
1671 end do
1672
1673 ! Discard first 4*r results (Gimeno)
1674 i(j) = r - 1
1675 do k = 4 * r, 1, -1
1676 i(j) = iand(i(j) + 1, r - 1)
1677 t(j) = x(j, i(j))
1678 v(j) = x(j, iand(i(j) + (r - s), r - 1))
1679 t(j) = ieor(t(j), ishft(t(j), a))
1680 t(j) = ieor(t(j), ishft(t(j), -b))
1681 v(j) = ieor(v(j), ishft(v(j), c))
1682 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
1683 x(j, i(j)) = v(j)
1684 end do
1685 flag(j) = 1
1686 end if ! end of initialization
1687 end do
1688
1689 Do j = 1, m !Loop over every stream
1690 If (flag(j) .eq. 1) then
1691 ! Polar method of Box-Mueller-transform to generate Gaussian distributed random number
1692 ww(j) = 1.0_sp
1693 do while (ww(j) .ge. 1.0_sp)
1694
1695 ! Apart from initialization (above), this is the generator
1696 v(j) = 0_i4
1697 Do While (v(j) .eq. 0_i4)
1698 i(j) = iand(i(j) + 1, r - 1)
1699 t(j) = x(j, i(j))
1700 v(j) = x(j, iand(i(j) + (r - s), r - 1))
1701 t(j) = ieor(t(j), ishft(t(j), a))
1702 t(j) = ieor(t(j), ishft(t(j), -b))
1703 v(j) = ieor(v(j), ishft(v(j), c))
1704 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
1705 x(j, i(j)) = v(j)
1706 w(j) = w(j) + weyl
1707 v(j) = v(j) + w(j)
1708 v(j) = ishft(v(j), -8)
1709 End Do
1710
1711 rn1(j) = t24 * v(j)
1712
1713 v(j) = 0_i4
1714 Do While (v(j) .eq. 0_i4)
1715 i(j) = iand(i(j) + 1, r - 1)
1716 t(j) = x(j, i(j))
1717 v(j) = x(j, iand(i(j) + (r - s), r - 1))
1718 t(j) = ieor(t(j), ishft(t(j), a))
1719 t(j) = ieor(t(j), ishft(t(j), -b))
1720 v(j) = ieor(v(j), ishft(v(j), c))
1721 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
1722 x(j, i(j)) = v(j)
1723 w(j) = w(j) + weyl
1724 v(j) = v(j) + w(j)
1725 v(j) = ishft(v(j), -8)
1726 End Do
1727
1728 rn2(j) = t24 * v(j)
1729
1730 x1(j) = 2.0_sp * rn1(j) - 1.0_sp
1731 x2(j) = 2.0_sp * rn2(j) - 1.0_sp
1732 ww(j) = x1(j) * x1(j) + x2(j) * x2(j)
1733 end do ! end of polar method
1734
1735 ww(j) = sqrt((-2.0_sp * log(ww(j))) / ww(j))
1736 y1(j) = x1(j) * ww(j)
1737 y2(j) = x2(j) * ww(j)
1738 end if ! Only if Flag = 1
1739 end do ! Loop over each stream
1740
1741 Do j = 1, m
1742 If (flag(j) .eq. 1) then
1743 flag(j) = 2
1744 singlerealrn(j) = y1(j)
1745 else
1746 flag(j) = 1
1747 singlerealrn(j) = y2(j)
1748 end if
1749 end Do
1750
1751 if(present(save_state)) then
1752 save_state(:, 1 : r) = x(:, 0 : r - 1)
1753 save_state(:, r + 1) = i(:)
1754 save_state(:, r + 2) = w(:)
1755 save_state(:, r + 3) = flag(:)
1756 do j = 1, m
1757 save_state(j, r + 4) = transfer(y2(j), 1_i4)
1758 end do
1759 if ((r + 5) <= n_save_state) save_state(:, r + 5 : n_save_state) = 0
1760 end if
1761
1762 end subroutine xor4096gf_1d
1763
1764 ! -----------------------------------------------------------------------------
1765
1766 subroutine xor4096gd_0d(seed, DoubleRealRN, save_state)
1767
1768 implicit none
1769
1770 integer(i8), intent(in) :: seed
1771 real(dp), intent(out) :: doublerealrn
1772 integer(i8), optional, dimension(n_save_state), intent(inout) :: save_state
1773
1774 integer(i8) :: wlen, r, s, a, b, c, d
1775
1776 integer(i8), save :: w
1777 integer(i8), save :: x(0 : 63) ! x(0) ... x(r-1)
1778 integer(i8) :: weyl = 7046029254386353131_i8
1779 integer(i8) :: t, v, tmp
1780 integer(i8), save :: i = -1_i8 ! i<0 indicates first call
1781 integer(i8) :: k
1782
1783 real(dp) :: t53 = 1.0_dp / 9007199254740992.0_dp ! = 0.5^53 = 1/2^53
1784
1785 real(dp) :: rn1, rn2 ! uniform random numbers
1786 real(dp) :: x1, x2, y1, ww ! for Box-Mueller transform
1787 real(dp), save :: y2
1788 integer(i8), save :: flag = 1_i8 ! if Flag = 1 return y1 else return y2
1789
1790 !$omp threadprivate(x,i,w,y2,flag)
1791
1792 ! produces a 53bit Integer Random Number (0...9 007 199 254 740 992) and
1793 ! scales it afterwards to (0.0,1.0)
1794 ! transform using polar-method
1795
1796 wlen = 64_i8
1797 r = 64_i8
1798 s = 53_i8
1799 a = 33_i8
1800 b = 26_i8
1801 c = 27_i8
1802 d = 29_i8
1803
1804 if(present(save_state) .and. (seed .eq. 0)) then
1805 x(0 : r - 1) = save_state(1 : r)
1806 i = save_state(r + 1)
1807 w = save_state(r + 2)
1808 flag = save_state(r + 3)
1809 y2 = transfer(save_state(r + 4), 1.0_dp)
1810 end if
1811
1812 If ((i .lt. 0_i8) .or. (seed .ne. 0_i8)) then ! Initialization necessary
1813 If (seed .ne. 0) then ! v must be nonzero
1814 v = seed
1815 else
1816 v = not(seed)
1817 end if
1818
1819 do k = wlen, 1, -1 ! Avoid correlations for close seeds
1820 ! This recurrence has period of 2^64-1
1821 v = ieor(v, ishft(v, 7))
1822 v = ieor(v, ishft(v, -9))
1823 end do
1824
1825 ! Initialize circular array
1826 w = v
1827 do k = 0, r - 1
1828 ! w = w + weyl
1829 if (w < 0_i8) then
1830 w = w + weyl
1831 else if ((huge(1_i8) - w) > weyl) then
1832 w = w + weyl
1833 else
1834 tmp = -(huge(1_i8) - w - weyl)
1835 w = tmp - huge(1_i8) - 2_i8
1836 endif
1837 v = ieor(v, ishft(v, 7))
1838 v = ieor(v, ishft(v, -9))
1839 x(k) = v + w
1840 end do
1841
1842 ! Discard first 4*r results (Gimeno)
1843 i = r - 1
1844 do k = 4 * r, 1, -1
1845 i = iand(i + 1, r - 1)
1846 t = x(i)
1847 v = x(iand(i + (r - s), r - 1))
1848 t = ieor(t, ishft(t, a))
1849 t = ieor(t, ishft(t, -b))
1850 v = ieor(v, ishft(v, c))
1851 v = ieor(v, ieor(t, ishft(v, -d)))
1852 x(i) = v
1853 end do
1854 flag = 1_i8
1855 end if ! end of initialization
1856
1857 If (flag .eq. 1_i8) then
1858 ! Polar method of Box-Mueller-transform to generate Gaussian distributed random number
1859 ww = 1.0_dp
1860 do while (ww .ge. 1.0_dp)
1861
1862 ! Apart from initialization (above), this is the generator
1863 v = 0_i8
1864 Do While (v .eq. 0_i8)
1865 i = iand(i + 1, r - 1)
1866 t = x(i)
1867 v = x(iand(i + (r - s), r - 1))
1868 t = ieor(t, ishft(t, a))
1869 t = ieor(t, ishft(t, -b))
1870 v = ieor(v, ishft(v, c))
1871 v = ieor(v, ieor(t, ishft(v, -d)))
1872 x(i) = v
1873 w = w + weyl
1874 v = v + w
1875 v = ishft(v, -11)
1876 End Do
1877
1878 rn1 = t53 * v
1879
1880 v = 0_i8
1881 Do While (v .eq. 0_i8)
1882 i = iand(i + 1, r - 1)
1883 t = x(i)
1884 v = x(iand(i + (r - s), r - 1))
1885 t = ieor(t, ishft(t, a))
1886 t = ieor(t, ishft(t, -b))
1887 v = ieor(v, ishft(v, c))
1888 v = ieor(v, ieor(t, ishft(v, -d)))
1889 x(i) = v
1890 w = w + weyl
1891 v = v + w
1892 v = ishft(v, -11)
1893 End Do
1894
1895 rn2 = t53 * v
1896
1897 x1 = 2.0_dp * rn1 - 1.0_dp
1898 x2 = 2.0_dp * rn2 - 1.0_dp
1899 ww = x1 * x1 + x2 * x2
1900 end do ! end of polar method
1901
1902 ww = sqrt((-2.0_dp * log(ww)) / ww)
1903 y1 = x1 * ww
1904 y2 = x2 * ww
1905
1906 end if ! Only if Flag = 1
1907
1908 If (flag .eq. 1) then
1909 flag = 2
1910 doublerealrn = y1
1911 else
1912 flag = 1
1913 doublerealrn = y2
1914 end if
1915
1916 if(present(save_state)) then
1917 save_state(1 : r) = x(0 : r - 1)
1918 save_state(r + 1) = i
1919 save_state(r + 2) = w
1920 save_state(r + 3) = flag
1921 save_state(r + 4) = transfer(y2, 1_i8)
1922 if ((r + 5) <= n_save_state) save_state(r + 5 : n_save_state) = 0
1923 end if
1924
1925 end subroutine xor4096gd_0d
1926
1927 ! -----------------------------------------------------------------------------
1928
1929 subroutine xor4096gd_1d(seed, DoubleRealRN, save_state)
1930
1931 implicit none
1932
1933 integer(i8), dimension(:), intent(in) :: seed
1934 real(dp), dimension(size(seed)), intent(out) :: doublerealrn
1935 integer(i8), optional, dimension(size(seed), n_save_state), intent(inout) :: save_state
1936
1937 integer(i4) :: m
1938 integer(i8) :: wlen, r, s, a, b, c, d
1939 integer(i8) :: weyl = 7046029254386353131_i8 !Z'61C88647' = Hexadecimal notation
1940 integer(i8) :: k, j, tmp
1941 real(dp) :: t53 = 1.0_dp / 9007199254740992.0_dp ! = 0.5^24 = 1/2^24
1942 integer(i8), dimension(size(seed)) :: t, v
1943 integer(i8), dimension(:, :), allocatable, save :: x ! x(0) ... x(r-1)
1944 integer(i8), dimension(:), allocatable, save :: i, w ! i<0 indicates first call
1945
1946 real(dp), dimension(size(seed)) :: rn1, rn2 ! uniform random numbers
1947 real(dp), dimension(size(seed)) :: x1, x2, y1, ww ! for Box-Mueller transform
1948 real(dp), dimension(:), allocatable, save :: y2
1949 integer(i8), dimension(:), allocatable, save :: flag ! if Flag = 1 return y1 else return y2
1950
1951 !$omp threadprivate(x,i,w,y2,flag)
1952
1953 ! produces a 53bit Integer Random Number (0...9 007 199 254 740 992) and
1954 ! scales it afterwards to (0.0,1.0)
1955 ! transform using polar-method
1956
1957 wlen = 64_i8
1958 r = 64_i8
1959 s = 53_i8
1960 a = 33_i8
1961 b = 26_i8
1962 c = 27_i8
1963 d = 29_i8
1964
1965 m = size(seed, 1)
1966
1967 if (any(seed .eq. 0_i8) .and. any(seed .ne. 0_i8)) then
1968 stop 'xor4096g: seeds have to be eigther all 0 or all larger than 0'
1969 end if
1970
1971 if (present(save_state) .and. all(seed .eq. 0_i8)) then
1972 if (allocated(x)) then
1973 if (size(x, 1) .ne. m) then
1974 deallocate(x)
1975 deallocate(i)
1976 deallocate(w)
1977 deallocate(flag)
1978 deallocate(y2)
1979 allocate(i(m))
1980 allocate(x(m, 0 : r - 1))
1981 allocate(w(m))
1982 allocate(flag(m))
1983 allocate(y2(m))
1984 end if
1985 end if
1986 if (.not. allocated(x)) then
1987 allocate(i(m))
1988 allocate(x(m, 0 : r - 1))
1989 allocate(w(m))
1990 allocate(flag(m))
1991 allocate(y2(m))
1992 end if
1993 x(:, 0 : r - 1) = save_state(:, 1 : r)
1994 i(:) = save_state(:, r + 1)
1995 w(:) = save_state(:, r + 2)
1996 flag(:) = save_state(:, r + 3)
1997 do j = 1, m
1998 y2(j) = transfer(save_state(j, r + 4), 1.0_dp)
1999 end do
2000 end if
2001
2002 if(all(seed .ne. 0_i8)) then
2003 if (allocated(x)) then
2004 deallocate(x)
2005 deallocate(i)
2006 deallocate(w)
2007 deallocate(flag)
2008 deallocate(y2)
2009 end if
2010
2011 allocate(i(m))
2012 i = -1
2013 allocate(x(m, 0 : r - 1))
2014 allocate(w(m))
2015 allocate(flag(m))
2016 flag = 1
2017 allocate(y2(m))
2018 end if
2019
2020 Do j = 1, m !Loop over every stream
2021 If ((i(j) .lt. 0) .or. (seed(j) .ne. 0)) then ! Initialization necessary
2022 If (seed(j) .ne. 0) then ! v must be nonzero
2023 v(j) = seed(j)
2024 else
2025 v(j) = not(seed(j))
2026 end if
2027
2028 do k = wlen, 1, -1 ! Avoid correlations for close seeds
2029 ! This recurrence has period of 2^64-1
2030 v(j) = ieor(v(j), ishft(v(j), 7))
2031 v(j) = ieor(v(j), ishft(v(j), -9))
2032 end do
2033
2034 ! Initialize circular array
2035 w(j) = v(j)
2036 do k = 0, r - 1
2037 ! w(j) = w(j) + weyl
2038 if (w(j) < 0_i8) then
2039 w(j) = w(j) + weyl
2040 else if ((huge(1_i8) - w(j)) > weyl) then
2041 w(j) = w(j) + weyl
2042 else
2043 tmp = -(huge(1_i8) - w(j) - weyl)
2044 w(j) = tmp - huge(1_i8) - 2_i8
2045 endif
2046 v(j) = ieor(v(j), ishft(v(j), 7))
2047 v(j) = ieor(v(j), ishft(v(j), -9))
2048 x(j, k) = v(j) + w(j)
2049 end do
2050
2051 ! Discard first 4*r results (Gimeno)
2052 i(j) = r - 1
2053 do k = 4 * r, 1, -1
2054 i(j) = iand(i(j) + 1, r - 1)
2055 t(j) = x(j, i(j))
2056 v(j) = x(j, iand(i(j) + (r - s), r - 1))
2057 t(j) = ieor(t(j), ishft(t(j), a))
2058 t(j) = ieor(t(j), ishft(t(j), -b))
2059 v(j) = ieor(v(j), ishft(v(j), c))
2060 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
2061 x(j, i(j)) = v(j)
2062 end do
2063 flag(j) = 1
2064 end if ! end of initialization
2065 end do
2066
2067 Do j = 1, m !Loop over every stream
2068 If (flag(j) .eq. 1) then
2069 ! Polar method of Box-Mueller-transform to generate Gaussian distributed random number
2070 ww(j) = 1.0_dp
2071 do while (ww(j) .ge. 1.0_dp)
2072
2073 ! Apart from initialization (above), this is the generator
2074 v(j) = 0_i8
2075 Do While (v(j) .eq. 0_i8)
2076 i(j) = iand(i(j) + 1, r - 1)
2077 t(j) = x(j, i(j))
2078 v(j) = x(j, iand(i(j) + (r - s), r - 1))
2079 t(j) = ieor(t(j), ishft(t(j), a))
2080 t(j) = ieor(t(j), ishft(t(j), -b))
2081 v(j) = ieor(v(j), ishft(v(j), c))
2082 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
2083 x(j, i(j)) = v(j)
2084 w(j) = w(j) + weyl
2085 v(j) = v(j) + w(j)
2086 v(j) = ishft(v(j), -11)
2087 End Do
2088
2089 rn1(j) = t53 * v(j)
2090
2091 v(j) = 0_i8
2092 Do While (v(j) .eq. 0_i8)
2093 i(j) = iand(i(j) + 1, r - 1)
2094 t(j) = x(j, i(j))
2095 v(j) = x(j, iand(i(j) + (r - s), r - 1))
2096 t(j) = ieor(t(j), ishft(t(j), a))
2097 t(j) = ieor(t(j), ishft(t(j), -b))
2098 v(j) = ieor(v(j), ishft(v(j), c))
2099 v(j) = ieor(v(j), ieor(t(j), ishft(v(j), -d)))
2100 x(j, i(j)) = v(j)
2101 w(j) = w(j) + weyl
2102 v(j) = v(j) + w(j)
2103 v(j) = ishft(v(j), -11)
2104 End Do
2105
2106 rn2(j) = t53 * v(j)
2107
2108 x1(j) = 2.0_dp * rn1(j) - 1.0_dp
2109 x2(j) = 2.0_dp * rn2(j) - 1.0_dp
2110 ww(j) = x1(j) * x1(j) + x2(j) * x2(j)
2111 end do ! end of polar method
2112
2113 ww(j) = sqrt((-2.0_dp * log(ww(j))) / ww(j))
2114 y1(j) = x1(j) * ww(j)
2115 y2(j) = x2(j) * ww(j)
2116
2117 end if ! Only if Flag = 1
2118 end do ! Loop over each stream
2119
2120 Do j = 1, m
2121 If (flag(j) .eq. 1) then
2122 flag(j) = 2
2123 doublerealrn(j) = y1(j)
2124 else
2125 flag(j) = 1
2126 doublerealrn(j) = y2(j)
2127 end if
2128 End do
2129
2130 if(present(save_state)) then
2131 save_state(:, 1 : r) = x(:, 0 : r - 1)
2132 save_state(:, r + 1) = i(:)
2133 save_state(:, r + 2) = w(:)
2134 save_state(:, r + 3) = flag(:)
2135 do j = 1, m
2136 save_state(j, r + 4) = transfer(y2(j), 1_i8)
2137 end do
2138 if ((r + 5) <= n_save_state) save_state(:, r + 5 : n_save_state) = 0
2139 end if
2140
2141 end subroutine xor4096gd_1d
2142
2143end module mo_xor4096
Generate seed for xor4096.
Uniform XOR4096-based RNG.
Gaussian XOR4096-based RNG.
Define number representations.
Definition mo_kind.F90:17
integer, parameter sp
Single Precision Real Kind.
Definition mo_kind.F90:44
integer, parameter i4
4 Byte Integer Kind
Definition mo_kind.F90:40
integer, parameter i8
8 Byte Integer Kind
Definition mo_kind.F90:42
integer, parameter dp
Double Precision Real Kind.
Definition mo_kind.F90:46
XOR4096-based random number generator.
integer(i4), parameter, public n_save_state
Dimension of vector saving the state of a stream.