[Dart-dev] [5611] DART/branches/development/random_seq/random_seq_mod.f90: various fixes to errors in code after a code review.
nancy at ucar.edu
nancy at ucar.edu
Mon Mar 19 10:38:52 MDT 2012
Revision: 5611
Author: nancy
Date: 2012-03-19 10:38:52 -0600 (Mon, 19 Mar 2012)
Log Message:
-----------
various fixes to errors in code after a code review.
Modified Paths:
--------------
DART/branches/development/random_seq/random_seq_mod.f90
-------------- next part --------------
Modified: DART/branches/development/random_seq/random_seq_mod.f90
===================================================================
--- DART/branches/development/random_seq/random_seq_mod.f90 2012-03-19 15:11:09 UTC (rev 5610)
+++ DART/branches/development/random_seq/random_seq_mod.f90 2012-03-19 16:38:52 UTC (rev 5611)
@@ -13,7 +13,7 @@
! $Revision$
! $Date$
-use types_mod, only : r8, digits12, i8
+use types_mod, only : digits12, i8, r8
use utilities_mod, only : register_module, error_handler, E_ERR
implicit none
@@ -45,9 +45,10 @@
integer, parameter :: M = 397
! hexadecimal constants
-integer(i8), parameter :: UPPER_MASK = z'80000000'
-integer(i8), parameter :: LOWER_MASK = z'7FFFFFFF'
-integer(i8), parameter :: magic = z'9908b0df'
+integer(i8), parameter :: UPPER_MASK = z'80000000'
+integer(i8), parameter :: LOWER_MASK = z'7FFFFFFF'
+integer(i8), parameter :: FULL32_MASK = z'FFFFFFFF'
+integer(i8), parameter :: magic = z'9908b0df'
type random_seq_type
private
@@ -194,15 +195,15 @@
sd = seed
if (sd == 0) sd = 4357 ! do not allow seed to be 0, use default
-s%mt(0) = iand(sd, z'FFFFFFFF')
+s%mt(0) = iand(sd, FULL32_MASK)
! See Knuth's "Art of Computer Programming" Vol. 2, 3rd Ed. p.106
! for multiplier.
do i=1, N-1
- s%mt(i) = 1812433253_i8 * (ieor(s%mt(i-1), ishft(s%mt(i-1), -30)) + i)
+ s%mt(i) = 1812433253_i8 * ieor(s%mt(i-1), ishft(s%mt(i-1), -30)) + i
- s%mt(i) = iand(s%mt(i), z'FFFFFFFF')
+ s%mt(i) = iand(s%mt(i), FULL32_MASK)
end do
s%mti = N
@@ -230,7 +231,7 @@
if (s%mti >= N) then
! generate N words at a time
- do kk = 0, N-M
+ do kk = 0, N-M-1
y = ior(iand(s%mt(kk), UPPER_MASK), iand(s%mt(kk + 1), LOWER_MASK))
if (iand(y,1_i8) == 1_i8) then
m1 = magic
@@ -245,7 +246,7 @@
enddo
- do kk = N-M, N-1
+ do kk = N-M, N-2
y = ior(iand(s%mt(kk), UPPER_MASK), iand(s%mt(kk + 1), LOWER_MASK))
if (iand(y,1_i8) == 1_i8) then
m1 = magic
@@ -297,7 +298,7 @@
! so divide here. i do not know if the expected
! range is [0,1) (0,1] (0,1) or [0,1]. will search docs.
-ran_unif = real(k, r8) / 4294967296.0_r8
+ran_unif = real(real(k, digits12) / 4294967296.0_digits12, r8)
end function ran_unif
@@ -316,24 +317,29 @@
if ( .not. module_initialized ) call initialize_module
-10 continue
+! each pass through this code generates 2 values. if we have one
+! saved from a previous call, return it without doing any new work.
+! otherwise, generate 2 new values; return one and save the other.
-! choose x,y in uniform square (-1,-1) to (+1,+1)
-x = -1.0_digits12 + 2.0_digits12 * ran_unif(s)
-y = -1.0_digits12 + 2.0_digits12 * ran_unif(s)
-
-! repeat if it is outside the unit circle or at origin
-r2 = x*x + y*y
-if (r2 > 1.0_digits12 .or. r2 == 0.0_digits12) goto 10
-
if (s%gset) then
ran_gauss = s%lastg
s%gset = .false.
else
+
+ 10 continue
+
+ ! choose x,y in uniform square (-1,-1) to (+1,+1)
+ x = -1.0_digits12 + 2.0_digits12 * ran_unif(s)
+ y = -1.0_digits12 + 2.0_digits12 * ran_unif(s)
+
+ ! repeat if it is outside the unit circle or at origin
+ r2 = x*x + y*y
+ if (r2 >= 1.0_digits12 .or. r2 == 0.0_digits12) goto 10
+
t = sqrt(-2.0_digits12 * log(r2) / r2)
- s%lastg = x * t
+ s%lastg = real(x * t, r8)
s%gset = .true.
- ran_gauss = y * t
+ ran_gauss = real(y * t, r8)
endif
end function ran_gauss
More information about the Dart-dev
mailing list