Soil Water Balance (SWB2)
Toggle main menu visibility
Loading...
Searching...
No Matches
kiss_random_number_generator.F90
Go to the documentation of this file.
1
module
kiss_random_number_generator
2
3
use
iso_c_binding,
only
: c_int, c_float
4
use
iso_fortran_env,
only
: int64, real128
5
implicit none
6
7
integer (int64)
::
x
= 1234567890987654321_int64
8
integer (int64)
::
y
= 362436362436362436_int64
9
integer (int64)
::
z
= 1066149217761810_int64
10
integer (int64)
::
c
= 123456123456123456_int64
11
integer (int64)
::
t
12
13
contains
14
15
! original post found here:
16
! https://www.thecodingforums.com/threads/64-bit-kiss-rngs.673657/
17
18
! 64-bit KISS RNGs
19
!
20
! Consistent with the Keep It Simple Stupid (KISS) principle,
21
! I have previously suggested 32-bit KISS Random Number
22
! Generators (RNGs) that seem to have been frequently adopted.
23
!
24
! Having had requests for 64-bit KISSes, and now that
25
! 64-bit integers are becoming more available, I will
26
! describe here a 64-bit KISS RNG, with comments on
27
! implementation for various languages, speed, periods
28
! and performance after extensive tests of randomness.
29
!
30
! This 64-bit KISS RNG has three components, each nearly
31
! good enough to serve alone. The components are:
32
! Multiply-With-Carry (MWC), period (2^121+2^63-1)
33
! Xorshift (XSH), period 2^64-1
34
! Congruential (CNG), period 2^64
35
!
36
! Compact C and Fortran listings are given below. They
37
! can be cut, pasted, compiled and run to see if, after
38
! 100 million calls, results agree with that provided
39
! by theory, assuming the default seeds.
40
!
41
! Users may want to put the content in other forms, and,
42
! for general use, provide means to set the 250 seed bits
43
! required in the variables x,y,z (64 bits) and c (58 bits)
44
! that have been given default values in the test versions.
45
!
46
! The C version uses #define macros to enumerate the few
47
! instructions that MWC, XSH and CNG require. The KISS
48
! macro adds MWC+XSH+CNG mod 2^64, so that KISS can be
49
! inserted at any place in a C program where a random 64-bit
50
! integer is required.
51
! Fortran's requirement that integers be signed makes the
52
! necessary code more complicated, hence a function KISS().
53
!
54
! C version; test by invoking macro KISS 100 million times
55
! -----------------------------------------------------------------
56
! #include <stdio.h>
57
!
58
! static unsigned long long
59
! x=1234567890987654321ULL,c=123456123456123456ULL,
60
! y=362436362436362436ULL,z=1066149217761810ULL,t;
61
!
62
! #define MWC (t=(x<<58)+c, c=(x>>6), x+=t, c+=(x<t), x)
63
! #define XSH ( y^=(y<<13), y^=(y>>17), y^=(y<<43) )
64
! #define CNG ( z=6906969069LL*z+1234567 )
65
! #define KISS (MWC+XSH+CNG)
66
!
67
! int main(void)
68
! {int i;
69
! for(i=0;i<100000000;i++) t=KISS;
70
! (t==1666297717051644203ULL) ?
71
! printf("100 million uses of KISS OK"):
72
! printf("Fail");
73
! }
74
!
75
! ---------------------------------------------------------------
76
! Fortran version; test by calling KISS() 100 million times
77
! ---------------------------------------------------------------
78
! program testkiss
79
! implicit integer*8(a-z)
80
! do i=1,100000000; t=KISS(); end do
81
! if(t.eq.1666297717051644203_8) then
82
! print*,"100 million calls to KISS() OK"
83
! else; print*,"Fail"
84
! end if; end
85
!
86
! function KISS()
87
! implicit integer*8(a-z)
88
! data x,y,z,c /1234567890987654321_8, 362436362436362436_8,&
89
! 1066149217761810_8, 123456123456123456_8/
90
! save x,y,z,c
91
! m(x,k)=ieor(x,ishft(x,k)) !statement function
92
! s(x)=ishft(x,-63) !statement function
93
! t=ishft(x,58)+c
94
! if(s(x).eq.s(t)) then; c=ishft(x,-6)+s(x)
95
! else; c=ishft(x,-6)+1-s(x+t); endif
96
! x=t+x
97
! y=m(m(m(y,13_8),-17_8),43_8)
98
! z=6906969069_8*z+1234567
99
! KISS=x+y+z
100
! return; end
101
! ---------------------------------------------------------------
102
!
103
! Output from using the macro KISS or the function KISS() is
104
! MWC+XSH+CNG mod 2^64.
105
106
!-------------------------------------------------------------------------------
107
108
subroutine
kiss64_initialize
(seed)
109
110
integer (kind=c_int)
,
optional
:: seed
111
integer (int64)
:: indx
112
integer (int64)
:: pseudorandom_value
113
114
x
= 1234567890987654321_int64
115
y
= 362436362436362436_int64
116
z
= 1066149217761810_int64
117
c
= 123456123456123456_int64
118
119
if
(
present
(seed))
then
120
121
do
indx=1,seed
122
pseudorandom_value =
kiss64_rng
()
123
end do
124
125
endif
126
127
end subroutine
kiss64_initialize
128
129
!-------------------------------------------------------------------------------
130
131
function
kiss64_uniform_rng
()
result
(unif)
132
133
real
(c_float) :: unif
134
135
! [ LOCALS ]
136
integer (int64)
::
x
137
real
(real128) :: range
138
139
range = 2.0_real128 * real(huge(1_int64), kind=real128)
140
141
x
=
kiss64_rng
()
142
unif = real(( real(
x
, kind=real128) + real(huge(1_int64), kind=real128)) / range, c_float)
143
144
end function
kiss64_uniform_rng
145
146
!-------------------------------------------------------------------------------
147
148
function
bitwise_exclusive_or_operation
(x, k)
result
(m)
149
150
integer (int64)
::
x
, k
151
integer (int64)
:: m
152
153
m = ieor(
x
, ishft(
x
,k))
154
155
end function
bitwise_exclusive_or_operation
156
157
!-------------------------------------------------------------------------------
158
159
function
shift_bits
(x)
result
(y)
160
161
integer (int64)
::
x
162
integer (int64)
::
y
163
164
y
= ishft(
x
, -63)
165
166
end function
shift_bits
167
168
!-------------------------------------------------------------------------------
169
170
function
kiss64_rng
()
result
(pseudorandom_value)
171
integer (int64)
:: pseudorandom_value
172
173
t
= ishft(
x
, 58) +
c
174
175
if
(
shift_bits
(
x
) .eq.
shift_bits
(
t
))
then
176
c
= ishft(
x
, -6) +
shift_bits
(
x
)
177
else
178
c
= ishft(
x
, -6) + 1 -
shift_bits
(
x
+
t
)
179
endif
180
181
x
=
t
+
x
182
y
=
bitwise_exclusive_or_operation
( &
183
bitwise_exclusive_or_operation
( &
184
bitwise_exclusive_or_operation
(
y
,13_int64),-17_int64), 43_int64)
185
z
= 6906969069_int64 *
z
+ 1234567
186
pseudorandom_value =
x
+
y
+
z
187
188
end function
kiss64_rng
189
190
!-------------------------------------------------------------------------------
191
192
end module
kiss_random_number_generator
kiss_random_number_generator
Definition
kiss_random_number_generator.F90:1
kiss_random_number_generator::shift_bits
integer(int64) function shift_bits(x)
Definition
kiss_random_number_generator.F90:160
kiss_random_number_generator::z
integer(int64) z
Definition
kiss_random_number_generator.F90:9
kiss_random_number_generator::kiss64_uniform_rng
real(c_float) function kiss64_uniform_rng()
Definition
kiss_random_number_generator.F90:132
kiss_random_number_generator::kiss64_rng
integer(int64) function kiss64_rng()
Definition
kiss_random_number_generator.F90:171
kiss_random_number_generator::y
integer(int64) y
Definition
kiss_random_number_generator.F90:8
kiss_random_number_generator::t
integer(int64) t
Definition
kiss_random_number_generator.F90:11
kiss_random_number_generator::c
integer(int64) c
Definition
kiss_random_number_generator.F90:10
kiss_random_number_generator::kiss64_initialize
subroutine kiss64_initialize(seed)
Definition
kiss_random_number_generator.F90:109
kiss_random_number_generator::bitwise_exclusive_or_operation
integer(int64) function bitwise_exclusive_or_operation(x, k)
Definition
kiss_random_number_generator.F90:149
kiss_random_number_generator::x
integer(int64) x
Definition
kiss_random_number_generator.F90:7
src
kiss_random_number_generator.F90
Generated on
for Soil Water Balance (SWB2) by
1.17.0