    MODULE randmod
! .. Use Statements ..
      USE set_precision, ONLY : dp => dkind, sp=>skind
! ..
! .. Parameters ..
      REAL (dp), PARAMETER :: halfdp = 0.5E0_dp
      REAL (dp), PARAMETER :: onedp = 1.0E0_dp
      REAL (dp), PARAMETER :: twodp = 2.0E0_dp
      REAL (dp), PARAMETER :: zerodp = 0.0E0_dp
      INTEGER, PARAMETER :: udim = 97
! ..
! .. Local Scalars ..
      INTEGER, SAVE :: ix
! ..
! .. Local Arrays ..
      REAL (dp), SAVE :: u(udim)
! ..
    CONTAINS

      FUNCTION dpPortRand() RESULT (res)
!..Portable random number generator using the recursion 
!..       IX=IX*A MOD P
!.. From:
!.. A More Portable Fortran Random Number Generator,
!.. Linus Schrage, 
!.. ACM Trans. Math. Softw., Vol 5 (2), pp.132-138, June 1979.
! This will return double precision values in the range
! (0,1). The idea here isn't that the number generated are
! especially random but rather that the results are double
! precision and the lower bits are not all zero.
! We should get this courtesy of the fract value.
!..7**5, 2**15,  2**16, 2**31-1
! .. Function Return Value ..
        REAL (dp) :: res
! ..
! .. Parameters ..
        INTEGER, PARAMETER :: a = 16807, b15 = 32768, b16 = 65536, &
          p = 2147483647
        REAL (dp), PARAMETER :: fract = onedp/(twodp**31-onedp)
! ..
! .. Local Scalars ..
        INTEGER :: fhi, k, leftlo, xalo, xhi
! ..
! .. Intrinsic Functions ..
        INTRINSIC real
! ..

!..Get 15 high order bits of ix
        xhi = ix/b16
!..Get 16 lo bits of ix and form lo product
        xalo = (ix-xhi*b16)*a
!..Get 15 hi order bits of lo product
        leftlo = xalo/b16
!..Form the 31 highest bits of full product
        fhi = xhi*a + leftlo
!..Get overflow past 31st bit of full product
        k = fhi/b15
!..Assemble all the parts and presubtract p
!..The parentheses are essential
        ix = (((xalo-leftlo*b16)-p)+(fhi-k*b15)*b16) + k
!..Add p back in if necessary
        IF (ix<0) ix = ix + p
!..Multiply by 1/(2**31-1)
        res = real(ix,kind=dp)*fract
      END FUNCTION dpPortRand

      SUBROUTINE seed(iseed)

! Seed the portable random number generator

! .. Scalar Arguments ..
        INTEGER, INTENT (IN) :: iseed
! ..
        ix = iseed
      END SUBROUTINE seed

! If the user feels the need to employ an excellent 64-bit
! random number generator, the following is a Fortran 90
! implementation of the routine given in:
! 
! The 64-bit universal RNG
! George Marsaglia and Wai Wan Tsang
! Statistics and Probability Letters
! Vol. 66, Issue 2, pages 183-187, January 2004.
!
! To use this generator in oracle.f90 change the lines:
!
!    USE randMod, ONLY : seed, rand=>dpPortRand
!  to
!    USE randMod, ONLY : fillu, rand=>uni64
!
! and
!
!    CALL seed(42)
!  to
!    CALL fillu(123456789, 987654321) 
! 
! Warning: this code will fail if the compiler traps
!   integer (32-bit) overflows. 
!
      FUNCTION uni64() RESULT (res)
! .. Function Return Value ..
        REAL (dp) :: res
! ..
! .. Parameters ..
        REAL (dp), PARAMETER :: d = 362436069876.0E0_dp/ &
          9007199254740992.0E0_dp
        REAL (dp), PARAMETER :: r = 9007199254740881.0E0_dp/ &
          9007199254740992.0E0_dp
! ..
! .. Local Scalars ..
        REAL (dp), SAVE :: c = zerodp
        REAL (dp), SAVE :: x
        INTEGER, SAVE :: i = udim
        INTEGER, SAVE :: j = 33
! ..
        x = u(i) - u(j)
        IF (x<zerodp) x = x + onedp
        u(i) = x
        i = i - 1
        IF (i==0) i = udim
        j = j - 1
        IF (j==0) j = udim
        c = c - d
        IF (c<zerodp) c = c + r
        x = x - c
        res = x
        IF (x<zerodp) res = x + onedp
      END FUNCTION uni64

      SUBROUTINE fillu(seed1,seed2)
! .. Scalar Arguments ..
        INTEGER :: seed1, seed2
! ..
! .. Local Scalars ..
        REAL (dp) :: s, t
        INTEGER :: i, j, x, y
! ..
! .. Intrinsic Functions ..
        INTRINSIC iand, ieor, mod
! ..
        x = seed1
        y = seed2
        DO i = 1, udim
          s = zerodp
          t = halfdp
          DO j = 1, 53
            x = mod(6969*x,65543)
! Correction given in:
! http://mathforum.org/kb/message.jspa?messageID=4097288
! from Marsaglia has been applied
            y = mod(8888*y,65579)
            IF (iand(ieor(x,y),32)>0) s = s + t
            t = halfdp*t
          END DO
          u(i) = s
        END DO
      END SUBROUTINE fillu

  FUNCTION randomInt(minInt, maxInt) RESULT(res)
  INTEGER, INTENT(IN) :: minInt, maxInt
  INTEGER :: res
! Generate a random integer in the range [minInt, maxInt]
! Note: both end values are included in the range
! Use the Fortran standard random number generator to
! provide the random numbers in this case.
  REAL(sp) :: x

  x=REAL(dpPortrand(), KIND=sp)
  res = minInt + INT(x*REAL(maxInt-minInt+1, KIND=sp))

  END FUNCTION randomInt

END MODULE randmod
