FUNCTION rnorm() RESULT( fn_val ) ! Generate a random normal deviate using the polar method. ! Reference: Marsaglia,G. & Bray,T.A. 'A convenient method for generating ! normal variables', Siam Rev., vol.6, 260-264, 1964. IMPLICIT NONE REAL :: fn_val ! Local variables REAL :: u, sum REAL, SAVE :: v, sln LOGICAL, SAVE :: second = .FALSE. REAL, PARAMETER :: one = 1.0, vsmall = TINY( one ) IF (second) THEN ! If second, use the second random number generated on last call second = .false. fn_val = v*sln ELSE ! First call; generate a pair of random normals second = .true. DO CALL RANDOM_NUMBER( u ) CALL RANDOM_NUMBER( v ) u = SCALE( u, 1 ) - one v = SCALE( v, 1 ) - one sum = u*u + v*v + vsmall ! vsmall added to prevent LOG(zero) / zero IF(sum < one) EXIT END DO sln = SQRT(- SCALE( LOG(sum), 1 ) / sum) fn_val = u*sln END IF RETURN END FUNCTION rnorm