Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
kiss_random_number_generator.F90
Go to the documentation of this file.
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
13contains
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(x, kind=real128) + real(huge(1_int64), kind=real128)) / range
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
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
183 z = 6906969069_int64 * z + 1234567
184 pseudorandom_value = x + y + z
185
186 end function kiss64_rng
187
188!-------------------------------------------------------------------------------
189
integer(int64) function bitwise_exclusive_or_operation(x, k)