spral_random
- Pseudo-random number generator
Purpose
This package generates pseudo-random numbers using a linear congruential generator. It should generate the same random numbers using any standards compliant Fortran compiler on any architecture so long as the default integer and real kinds are the same.
The seed can optionally be observed or specified by the user. Otherwise a default seed of 486502 is used.
Version history
- 2016-09-08 Version 1.1.0
Add support for long integers
- 2014-04-07 Version 1.0.0
Initial release
Routines
Random Number Generation
- function random_real(state[, positive])
Return a real uniformly at random from the interval \((-1,1)\) (positive =.true.) or \((0,1)\) (positive =.false.).
- Parameters:
state [random_state ,inout] :: current state of RNG.
- Options:
positive [logical ,in,default=.false.] :: if .true., sample from \((0,1)\); otherwise, sample from \((-1,1)\).
- Return:
random_real [real] :: Sampled value.
- function random_integer(state, n)
Return an integer uniformly at random from the interval \([1,n]\).
- Parameters:
state [random_state ,inout] :: current state of the RNG.
n [integer(kind),in] :: largest value in range to be sampled. kind may be either default or long integer (return type will match).
- Return:
random_integer [integer(kind)] :: Sampled value.
- function random_logical(state)
Return a logical with equal probability of being .true. or .false..
- Parameters:
state [random_state ,inout] :: current state of the RNG.
- Return:
random_logical [logical] :: Sampled value.
Get/Set Random Seed
- function random_get_seed(state)
Return the current random seed stored in state.
The stream of random numbers generated after this call can be reproduced through the same sequence of calls after seed has been passed to
random_set_seed()
.- Parameters:
state [random_state ,in] :: state variable to extract state from
- Return:
random_get_seed :: current random seed
- subroutine random_set_seed(state, seed)
Set the random seed stored in the state variable
- Parameters:
state [random_state ,inout] :: state variable to set seed for.
seed [integer ,in] :: new seed.
Data Types
- type random_state
State of the random number generator. Compontents are not available to the user, but may be examined and altered through calls to
random_get_seed()
andrandom_set_seed()
respectively.
Example
The following code:
! examples/Fortran/random.f90 - Example code for SPRAL_RANDOM package
program random_example
use spral_random
implicit none
integer, parameter :: long = selected_int_kind(18)
type(random_state) :: state
integer :: seed
! Store initial random seed so we can reuse it later
seed = random_get_seed(state)
! Generate some random values
write(*,"(a)") "Some random values"
write(*,"(a,f16.12)") "Sample Unif(-1,1) = ", &
random_real(state)
write(*,"(a,f16.12)") "Sample Unif(0,1) = ", &
random_real(state, positive=.true.)
write(*,"(a,i16)") "Sample Unif(1, ..., 20) = ", &
random_integer(state, 20)
write(*,"(a,i16)") "Sample Unif(1, ..., 20*huge(0)) = ", &
random_integer(state, 20_long*huge(0))
write(*,"(a,l16)") "Sample B(1,0.5) = ", &
random_logical(state)
! Restore initial seed
call random_set_seed(state, seed)
! Generate the same random values
write(*,"(/a)") "The same random values again"
write(*,"(a,f16.12)") "Sample Unif(-1,1) = ", &
random_real(state)
write(*,"(a,f16.12)") "Sample Unif(0,1) = ", &
random_real(state, positive=.true.)
write(*,"(a,i16)") "Sample Unif(1, ..., 20) = ", &
random_integer(state, 20)
write(*,"(a,i16)") "Sample Unif(1, ..., 20*huge(0)) = ", &
random_integer(state, 20_long*huge(0))
write(*,"(a,l16)") "Sample B(1,0.5) = ", &
random_logical(state)
end program random_example
Produces the following output:
Some random values
Sample Unif(-1,1) = 0.951878630556
Sample Unif(0,1) = 0.395779648796
Sample Unif(1, ..., 20) = 3
Sample Unif(1, ..., 20*huge(0)) = 33572664025
Sample B(1,0.5) = F
The same random values again
Sample Unif(-1,1) = 0.951878630556
Sample Unif(0,1) = 0.395779648796
Sample Unif(1, ..., 20) = 3
Sample Unif(1, ..., 20*huge(0)) = 33572664025
Sample B(1,0.5) = F
Method
We use a linear congruential generator of the following form:
with the following constants
According to Wikipedia, this is the same as used in glibc.
The LCG is evolved before each sample is taken, and the sample is based on the new value.
The routines random_get_seed()
and random_set_seed()
allow the
user to get and set the current value of \(X_n\). The default seed is
\(X_0 = 486502\).
In random_real()
Samples from \(\mathrm{Unif}(0,1)\) are generated as
and samples from \(\mathrm{Unif}(-1,1)\) are generated as
In random_integer()
Samples from \(\mathrm{Unif}(1,\ldots,n)\) are generated as
In random_logical()
Returns the value of the Fortran expression
(1 .eq. random_integer(state,2))