splitmix64_next_exponential_int Function

private function splitmix64_next_exponential_int(gen, mean, err) result(r)

Exponential integer with the given mean, from a splitmix64_t generator.

Arguments

Type IntentOptional Attributes Name
type(splitmix64_t), intent(inout) :: gen

Generator, advanced by one draw, or more in the tail.

integer(kind=int64), intent(in) :: mean

Mean of the distribution, in [0, EXPONENTIAL_MAX_MEAN].

type(error_t), intent(inout), optional :: err

Set to ERROR_VALIDATION when mean is out of range.

Return Value integer(kind=int64)


Calls

proc~~splitmix64_next_exponential_int~~CallsGraph proc~splitmix64_next_exponential_int splitmix64_next_exponential_int proc~error_set error_t%error_set proc~splitmix64_next_exponential_int->proc~error_set proc~scale_by_mean scale_by_mean proc~splitmix64_next_exponential_int->proc~scale_by_mean proc~splitmix64_next_u64 splitmix64_t%splitmix64_next_u64 proc~splitmix64_next_exponential_int->proc~splitmix64_next_u64 proc~u64_shr u64_shr proc~splitmix64_next_exponential_int->proc~u64_shr proc~scale_by_mean->proc~u64_shr proc~splitmix64_next splitmix64_t%splitmix64_next proc~splitmix64_next_u64->proc~splitmix64_next proc~mix64 mix64 proc~splitmix64_next->proc~mix64 proc~u64_add u64_add proc~splitmix64_next->proc~u64_add proc~mix64->proc~u64_shr proc~u64_mul u64_mul proc~mix64->proc~u64_mul

Called by

proc~~splitmix64_next_exponential_int~~CalledByGraph proc~splitmix64_next_exponential_int splitmix64_next_exponential_int interface~next_exponential_int next_exponential_int interface~next_exponential_int->proc~splitmix64_next_exponential_int proc~splitmix64_next_poisson_int splitmix64_next_poisson_int proc~splitmix64_next_poisson_int->proc~splitmix64_next_exponential_int interface~next_poisson_int next_poisson_int interface~next_poisson_int->proc~splitmix64_next_poisson_int

Variables

Type Visibility Attributes Name Initial
integer(kind=default_int), private :: cell
integer(kind=default_int), private :: frac
integer(kind=int64), private :: gap
integer(kind=default_int), private :: turns
integer(kind=int64), private :: word
integer(kind=int64), private :: x_q32

Source Code

   function splitmix64_next_exponential_int(gen, mean, err) result(r)
      !! Exponential integer with the given mean, from a splitmix64_t generator.
      type(splitmix64_t), intent(inout) :: gen
         !! Generator, advanced by one draw, or more in the tail.
      integer(int64), intent(in) :: mean
         !! Mean of the distribution, in `[0, EXPONENTIAL_MAX_MEAN]`.
      type(error_t), intent(inout), optional :: err
         !! Set to `ERROR_VALIDATION` when `mean` is out of range.
      integer(int64) :: r

      integer(int64) :: word, x_q32, gap
      integer(default_int) :: cell, frac, turns

      r = 0_int64
      if (mean < 0_int64 .or. mean > EXPONENTIAL_MAX_MEAN) then
         if (present(err)) then
            call err%set(ERROR_VALIDATION, &
                         "pic_random_dist: next_exponential_int mean out of range")
         end if
         return
      end if
      if (mean == 0_int64) return

      x_q32 = 0_int64
      turns = 0_default_int
      do
         word = gen%next_u64()
         cell = int(ibits(word, 0_default_int, EXP_CELL_BITS), default_int)
         if (cell < EXP_TOP_CELL .or. turns >= EXP_MAX_TAIL) then
            if (cell >= EXP_TOP_CELL) cell = EXP_TOP_CELL - 1_default_int
            frac = int(ibits(word, 33_default_int, FRAC_BITS), default_int)
            gap = EXP_TABLE(cell + 1_default_int) - EXP_TABLE(cell)
            x_q32 = x_q32 + EXP_TABLE(cell) + u64_shr(gap*int(frac, int64), FRAC_BITS)
            exit
         end if
         x_q32 = x_q32 + EXP_LN_CELLS
         turns = turns + 1_default_int
      end do
      r = scale_by_mean(x_q32, mean)
   end function splitmix64_next_exponential_int