random_binomial1 Function

function random_binomial1(n, p, first) result(ival)

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n
real, intent(in) :: p
logical, intent(in) :: first

Return Value integer


Calls

proc~~random_binomial1~~CallsGraph proc~random_binomial1 random_binomial1 bin_prob bin_prob proc~random_binomial1->bin_prob

Source Code

FUNCTION random_binomial1(n, p, first) RESULT(ival)
  ! FUNCTION GENERATES A RANDOM BINOMIAL VARIATE USING C.D.Kemp's method.
  ! This algorithm is suitable when many random variates are required
  ! with the SAME parameter values for n & p.
  !    P = BERNOULLI SUCCESS PROBABILITY
  !           (0 <= REAL <= 1)
  !    N = NUMBER OF BERNOULLI TRIALS
  !           (1 <= INTEGER)
  !    FIRST = .TRUE. for the first call using the current parameter values
  !          = .FALSE. if the values of (n,p) are unchanged from last call
  ! Reference: Kemp, C.D. (1986). `A modal method for generating binomial
  !            variables', Commun. Statist. - Theor. Meth. 15(3), 805-813.
  INTEGER, INTENT(IN) :: n
  REAL, INTENT(IN)    :: p
  LOGICAL, INTENT(IN) :: first
  INTEGER             :: ival
  !     Local variables
  INTEGER         :: ru, rd
  INTEGER, SAVE   :: r0
  REAL            :: u, pd, pu
  REAL, SAVE      :: odds_ratio, p_r
  REAL, PARAMETER :: zero = 0.0, one = 1.0
  IF (first) THEN
     r0 = (n+1)*p
     p_r = bin_prob(n, p, r0)
     odds_ratio = p / (one - p)
  END IF
  CALL RANDOM_NUMBER(u)
  u = u - p_r
  IF (u < zero) THEN
     ival = r0
     RETURN
  END IF
  pu = p_r
  ru = r0
  pd = p_r
  rd = r0
  DO
     rd = rd - 1
     IF (rd >= 0) THEN
        pd = pd * (rd+1) / (odds_ratio * (n-rd))
        u = u - pd
        IF (u < zero) THEN
           ival = rd
           RETURN
        END IF
     END IF
     ru = ru + 1
     IF (ru <= n) THEN
        pu = pu * (n-ru+1) * odds_ratio / ru
        u = u - pu
        IF (u < zero) THEN
           ival = ru
           RETURN
        END IF
     END IF
  END DO
  !     This point should not be reached, but just in case:
  ival = r0
  RETURN
END FUNCTION random_binomial1