splitmix64_next_poisson_int Function

private function splitmix64_next_poisson_int(gen, mean_milli, err) result(r)

Poisson count with mean mean_milli/1000, from a splitmix64_t generator.

Arguments

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

Generator, advanced once per inter-arrival drawn.

integer(kind=default_int), intent(in) :: mean_milli

A thousand times the mean, in [0, POISSON_MAX_MEAN_MILLI].

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

Set to ERROR_VALIDATION when mean_milli is out of range.

Return Value integer(kind=int32)


Calls

proc~~splitmix64_next_poisson_int~~CallsGraph proc~splitmix64_next_poisson_int splitmix64_next_poisson_int proc~error_set error_t%error_set proc~splitmix64_next_poisson_int->proc~error_set proc~splitmix64_next_exponential_int splitmix64_next_exponential_int proc~splitmix64_next_poisson_int->proc~splitmix64_next_exponential_int 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_poisson_int~~CalledByGraph proc~splitmix64_next_poisson_int splitmix64_next_poisson_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=int64), private :: elapsed
integer(kind=int64), private :: gap_mean
integer(kind=int64), private :: window

Source Code

   function splitmix64_next_poisson_int(gen, mean_milli, err) result(r)
      !! Poisson count with mean `mean_milli/1000`, from a splitmix64_t generator.
      type(splitmix64_t), intent(inout) :: gen
         !! Generator, advanced once per inter-arrival drawn.
      integer(default_int), intent(in) :: mean_milli
         !! A thousand times the mean, in `[0, POISSON_MAX_MEAN_MILLI]`.
      type(error_t), intent(inout), optional :: err
         !! Set to `ERROR_VALIDATION` when `mean_milli` is out of range.
      integer(int32) :: r

      integer(int64) :: gap_mean, window, elapsed

      r = 0_int32
      if (mean_milli < 0_default_int .or. mean_milli > POISSON_MAX_MEAN_MILLI) then
         if (present(err)) then
            call err%set(ERROR_VALIDATION, &
                         "pic_random_dist: next_poisson_int mean_milli out of range")
         end if
         return
      end if
      if (mean_milli == 0_default_int) return

      ! Mean gap between arrivals, in window ticks: window / (mean_milli/1000).
      ! That division truncates, so the gap actually used is a little short of
      ! the one asked for, and the count over a fixed window comes out high --
      ! by up to 0.048%, worst at mean_milli = 999596.
      !
      ! Fixing the gap and deriving the window from it instead turns that
      ! round-off to the sampler's advantage: whatever gap the truncation
      ! landed on, the window is the one for which that gap is exactly right.
      ! The residual is the truncation of the window itself, under 1e-6
      ! relative.
      gap_mean = (POISSON_WINDOW*1000_int64)/int(mean_milli, int64)
      window = (gap_mean*int(mean_milli, int64))/1000_int64
      elapsed = 0_int64
      do
         elapsed = elapsed + splitmix64_next_exponential_int(gen, gap_mean)
         if (elapsed > window) exit
         r = r + 1_int32
      end do
   end function splitmix64_next_poisson_int