next_exponential_int Interface

public interface next_exponential_int

Draw an exponentially distributed integer with the given mean, in whatever unit mean is expressed in.

Sampling is a table lookup and two integer multiplies. EXP_TABLE holds the inverse CDF -ln(1 - k/4096) in Q32.32 fixed point, generated once by tools/autogen/gen_exp_table.py with 60-digit decimal arithmetic. Twelve random bits choose a cell, thirty-one more interpolate linearly inside it, and the result is scaled by mean.

The tail

The top cell runs to infinity and cannot be interpolated into. It is handled with the memorylessness of the exponential instead: if U is uniform on the top cell then -ln(1 - U) is distributed as ln(4096) plus a fresh exponential, so the sampler adds ln(4096) and draws again. That is exact, and it costs an extra draw with probability 1/4096.

Capping the top entry at a finite value and interpolating into it – the obvious alternative – biases the mean by 0.147%. This scheme leaves 0.002%, and all of that residue is linear interpolation inside the body cells, not the tail.

mean must be in [0, EXPONENTIAL_MAX_MEAN]. A mean of zero always returns zero without consuming a draw. Out of range returns zero and, if err is present, sets ERROR_VALIDATION.

Calls

interface~~next_exponential_int~~CallsGraph interface~next_exponential_int next_exponential_int proc~pcg32_next_exponential_int pcg32_next_exponential_int interface~next_exponential_int->proc~pcg32_next_exponential_int proc~splitmix64_next_exponential_int splitmix64_next_exponential_int interface~next_exponential_int->proc~splitmix64_next_exponential_int proc~error_set error_t%error_set proc~pcg32_next_exponential_int->proc~error_set proc~pcg32_next_u64 pcg32_t%pcg32_next_u64 proc~pcg32_next_exponential_int->proc~pcg32_next_u64 proc~scale_by_mean scale_by_mean proc~pcg32_next_exponential_int->proc~scale_by_mean proc~u64_shr u64_shr proc~pcg32_next_exponential_int->proc~u64_shr proc~splitmix64_next_exponential_int->proc~error_set 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~splitmix64_next_exponential_int->proc~u64_shr proc~pcg32_step pcg32_step proc~pcg32_next_u64->proc~pcg32_step proc~scale_by_mean->proc~u64_shr proc~splitmix64_next splitmix64_t%splitmix64_next proc~splitmix64_next_u64->proc~splitmix64_next proc~pcg32_step->proc~u64_shr proc~rotate_right32 rotate_right32 proc~pcg32_step->proc~rotate_right32 proc~u64_add u64_add proc~pcg32_step->proc~u64_add proc~u64_mul u64_mul proc~pcg32_step->proc~u64_mul proc~mix64 mix64 proc~splitmix64_next->proc~mix64 proc~splitmix64_next->proc~u64_add proc~mix64->proc~u64_shr proc~mix64->proc~u64_mul

Module Procedures

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)

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

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

Arguments

Type IntentOptional Attributes Name
type(pcg32_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)