NCEPLIBS-w3emc 2.12.0
Loading...
Searching...
No Matches
mersenne_twister.f
Go to the documentation of this file.
1
4
96 private
97! Public declarations
98 public random_stat
99 public random_seed
100 public random_setseed
101 public random_number
102 public random_number_f
103 public random_gauss
104 public random_gauss_f
105 public random_index
106 public random_index_f
107! Parameters
108 integer,parameter:: n=624
109 integer,parameter:: m=397
110 integer,parameter:: mata=-1727483681 ! constant vector a
111 integer,parameter:: umask=-2147483648 ! most significant w-r bits
112 integer,parameter:: lmask =2147483647 ! least significant r bits
113 integer,parameter:: tmaskb=-1658038656 ! tempering parameter
114 integer,parameter:: tmaskc=-272236544 ! tempering parameter
115 integer,parameter:: mag01(0:1)=(/0,mata/)
116 integer,parameter:: iseed=4357
117 integer,parameter:: nrest=n+6
118! Defined types
120 private
121 integer:: mti=n+1
122 integer:: mt(0:n-1)
123 integer:: iset
124 real:: gset
125 end type
126! Saved data
127 type(random_stat),save:: sstat
128! Overloaded interfaces
130 module procedure random_setseed_s
131 module procedure random_setseed_t
132 end interface
134 module procedure random_number_i
135 module procedure random_number_s
136 module procedure random_number_t
137 end interface
138 interface random_gauss
139 module procedure random_gauss_i
140 module procedure random_gauss_s
141 module procedure random_gauss_t
142 end interface
143 interface random_index
144 module procedure random_index_i
145 module procedure random_index_s
146 module procedure random_index_t
147 end interface
148! All the subprograms
149 contains
150
158 subroutine random_seed(size,put,get,stat)
159 implicit none
160 integer,intent(out),optional:: size
161 integer,intent(in),optional:: put(nrest)
162 integer,intent(out),optional:: get(nrest)
163 type(random_stat),intent(inout),optional:: stat
164 if(present(size)) then ! return size of seed array
165! if(present(put).or.present(get))&
166! call errmsg('RANDOM_SEED: more than one option set - some ignored')
167 size=nrest
168 elseif(present(put)) then ! restore from seed array
169! if(present(get))&
170! call errmsg('RANDOM_SEED: more than one option set - some ignored')
171 if(present(stat)) then
172 stat%mti=put(1)
173 stat%mt=put(2:n+1)
174 stat%iset=put(n+2)
175 stat%gset=transfer(put(n+3:nrest),stat%gset)
176 if(stat%mti.lt.0.or.stat%mti.gt.n.or.any(stat%mt.eq.0).or.
177 & stat%iset.lt.0.or.stat%iset.gt.1) then
178 call random_setseed_t(iseed,stat)
179! call errmsg('RANDOM_SEED: invalid seeds put - default seeds used')
180 endif
181 else
182 sstat%mti=put(1)
183 sstat%mt=put(2:n+1)
184 sstat%iset=put(n+2)
185 sstat%gset=transfer(put(n+3:nrest),sstat%gset)
186 if(sstat%mti.lt.0.or.sstat%mti.gt.n.or.any(sstat%mt.eq.0)
187 & .or.sstat%iset.lt.0.or.sstat%iset.gt.1) then
188 call random_setseed_t(iseed,sstat)
189! call errmsg('RANDOM_SEED: invalid seeds put - default seeds used')
190 endif
191 endif
192 elseif(present(get)) then ! save to seed array
193 if(present(stat)) then
194 if(stat%mti.eq.n+1) call random_setseed_t(iseed,stat)
195 get(1)=stat%mti
196 get(2:n+1)=stat%mt
197 get(n+2)=stat%iset
198 get(n+3:nrest)=transfer(stat%gset,get,nrest-(n+3)+1)
199 else
200 if(sstat%mti.eq.n+1) call random_setseed_t(iseed,sstat)
201 get(1)=sstat%mti
202 get(2:n+1)=sstat%mt
203 get(n+2)=sstat%iset
204 get(n+3:nrest)=transfer(sstat%gset,get,nrest-(n+3)+1)
205 endif
206 else ! reset default seed
207 if(present(stat)) then
208 call random_setseed_t(iseed,stat)
209 else
210 call random_setseed_t(iseed,sstat)
211 endif
212 endif
213 end subroutine
214
219 subroutine random_setseed_s(inseed)
220 implicit none
221 integer,intent(in):: inseed
222 call random_setseed_t(inseed,sstat)
223 end subroutine
224
230 subroutine random_setseed_t(inseed,stat)
231 implicit none
232 integer,intent(in):: inseed
233 type(random_stat),intent(out):: stat
234 integer ii,mti
235 ii=inseed
236 if(ii.eq.0) ii=iseed
237 stat%mti=n
238 stat%mt(0)=iand(ii,-1)
239 do mti=1,n-1
240 stat%mt(mti)=iand(69069*stat%mt(mti-1),-1)
241 enddo
242 stat%iset=0
243 stat%gset=0.
244 end subroutine
245
250 function random_number_f() result(harvest)
251 implicit none
252 real:: harvest
253 real h(1)
254 if(sstat%mti.eq.n+1) call random_setseed_t(iseed,sstat)
255 call random_number_t(h,sstat)
256 harvest=h(1)
257 end function
258
264 subroutine random_number_i(harvest,inseed)
265 implicit none
266 real,intent(out):: harvest(:)
267 integer,intent(in):: inseed
268 type(random_stat) stat
269 call random_setseed_t(inseed,stat)
270 call random_number_t(harvest,stat)
271 end subroutine
272
277 subroutine random_number_s(harvest)
278 implicit none
279 real,intent(out):: harvest(:)
280 if(sstat%mti.eq.n+1) call random_setseed_t(iseed,sstat)
281 call random_number_t(harvest,sstat)
282 end subroutine
283
289 subroutine random_number_t(harvest,stat)
290 implicit none
291 real,intent(out):: harvest(:)
292 type(random_stat),intent(inout):: stat
293 integer j,kk,y
294 integer tshftu,tshfts,tshftt,tshftl
295 tshftu(y)=ishft(y,-11)
296 tshfts(y)=ishft(y,7)
297 tshftt(y)=ishft(y,15)
298 tshftl(y)=ishft(y,-18)
299 do j=1,size(harvest)
300 if(stat%mti.ge.n) then
301 do kk=0,n-m-1
302 y=ior(iand(stat%mt(kk),umask),iand(stat%mt(kk+1),lmask))
303 stat%mt(kk)=ieor(ieor(stat%mt(kk+m),ishft(y,-1)),
304 & mag01(iand(y,1)))
305 enddo
306 do kk=n-m,n-2
307 y=ior(iand(stat%mt(kk),umask),iand(stat%mt(kk+1),lmask))
308 stat%mt(kk)=ieor(ieor(stat%mt(kk+(m-n)),ishft(y,-1)),
309 & mag01(iand(y,1)))
310 enddo
311 y=ior(iand(stat%mt(n-1),umask),iand(stat%mt(0),lmask))
312 stat%mt(n-1)=ieor(ieor(stat%mt(m-1),ishft(y,-1)),
313 & mag01(iand(y,1)))
314 stat%mti=0
315 endif
316 y=stat%mt(stat%mti)
317 y=ieor(y,tshftu(y))
318 y=ieor(y,iand(tshfts(y),tmaskb))
319 y=ieor(y,iand(tshftt(y),tmaskc))
320 y=ieor(y,tshftl(y))
321 if(y.lt.0) then
322 harvest(j)=(real(y)+2.0**32)/(2.0**32-1.0)
323 else
324 harvest(j)=real(y)/(2.0**32-1.0)
325 endif
326 stat%mti=stat%mti+1
327 enddo
328 end subroutine
329
334 function random_gauss_f() result(harvest)
335 implicit none
336 real:: harvest
337 real h(1)
338 if(sstat%mti.eq.n+1) call random_setseed_t(iseed,sstat)
339 call random_gauss_t(h,sstat)
340 harvest=h(1)
341 end function
342
348 subroutine random_gauss_i(harvest,inseed)
349 implicit none
350 real,intent(out):: harvest(:)
351 integer,intent(in):: inseed
352 type(random_stat) stat
353 call random_setseed_t(inseed,stat)
354 call random_gauss_t(harvest,stat)
355 end subroutine
356
361 subroutine random_gauss_s(harvest)
362 implicit none
363 real,intent(out):: harvest(:)
364 if(sstat%mti.eq.n+1) call random_setseed_t(iseed,sstat)
365 call random_gauss_t(harvest,sstat)
366 end subroutine
367
373 subroutine random_gauss_t(harvest,stat)
374 implicit none
375 real,intent(out):: harvest(:)
376 type(random_stat),intent(inout):: stat
377 integer mx,my,mz,j
378 real r2(2),r,g1,g2
379 mz=size(harvest)
380 if(mz.le.0) return
381 mx=0
382 if(stat%iset.eq.1) then
383 mx=1
384 harvest(1)=stat%gset
385 stat%iset=0
386 endif
387 my=(mz-mx)/2*2+mx
388 do
389 call random_number_t(harvest(mx+1:my),stat)
390 do j=mx,my-2,2
391 call rgauss(harvest(j+1),harvest(j+2),r,g1,g2)
392 if(r.lt.1.) then
393 harvest(mx+1)=g1
394 harvest(mx+2)=g2
395 mx=mx+2
396 endif
397 enddo
398 if(mx.eq.my) exit
399 enddo
400 if(my.lt.mz) then
401 do
402 call random_number_t(r2,stat)
403 call rgauss(r2(1),r2(2),r,g1,g2)
404 if(r.lt.1.) exit
405 enddo
406 harvest(mz)=g1
407 stat%gset=g2
408 stat%iset=1
409 endif
410 contains
411
420 subroutine rgauss(r1,r2,r,g1,g2)
421 real,intent(in):: r1,r2
422 real,intent(out):: r,g1,g2
423 real v1,v2,fac
424 v1=2.*r1-1.
425 v2=2.*r2-1.
426 r=v1**2+v2**2
427 if(r.lt.1.) then
428 fac=sqrt(-2.*log(r)/r)
429 g1=v1*fac
430 g2=v2*fac
431 endif
432 end subroutine
433 end subroutine
434
440 function random_index_f(imax) result(iharvest)
441 implicit none
442 integer,intent(in):: imax
443 integer:: iharvest
444 integer ih(1)
445 if(sstat%mti.eq.n+1) call random_setseed_t(iseed,sstat)
446 call random_index_t(imax,ih,sstat)
447 iharvest=ih(1)
448 end function
449
456 subroutine random_index_i(imax,iharvest,inseed)
457 implicit none
458 integer,intent(in):: imax
459 integer,intent(out):: iharvest(:)
460 integer,intent(in):: inseed
461 type(random_stat) stat
462 call random_setseed_t(inseed,stat)
463 call random_index_t(imax,iharvest,stat)
464 end subroutine
465
471 subroutine random_index_s(imax,iharvest)
472 implicit none
473 integer,intent(in):: imax
474 integer,intent(out):: iharvest(:)
475 if(sstat%mti.eq.n+1) call random_setseed_t(iseed,sstat)
476 call random_index_t(imax,iharvest,sstat)
477 end subroutine
478
485 subroutine random_index_t(imax,iharvest,stat)
486 implicit none
487 integer,intent(in):: imax
488 integer,intent(out):: iharvest(:)
489 type(random_stat),intent(inout):: stat
490 integer,parameter:: mh=n
491 integer i1,i2,mz
492 real h(mh)
493 mz=size(iharvest)
494 do i1=1,mz,mh
495 i2=min((i1-1)+mh,mz)
496 call random_number_t(h(:i2-(i1-1)),stat)
497 iharvest(i1:i2)=max(ceiling(h(:i2-(i1-1))*imax),1)
498 enddo
499 end subroutine
500 end module
This module calculates random numbers using the Mersenne twister.
real function, public random_number_f()
Generates random numbers in functional mode.
subroutine, public random_seed(size, put, get, stat)
Sets and gets state; overloads Fortran 90 standard.
integer function, public random_index_f(imax)
Generates random indices in functional mode.
real function, public random_gauss_f()
Generates Gaussian random numbers in functional mode.