rng

import "github.com/umbralcalc/stochadex/pkg/rng"

Package rng provides a small, allocation-free random sampler for stochadex iterations and likelihood distributions. It is a drop-in, bit-identical replacement for the gonum distuv distribution draws the engine previously made, tuned to avoid their per-call overhead in hot loops.

Key Features:

Why this exists: The stochastic iterations previously drew from gonum’s distuv distributions, e.g. distuv.Normal{Mu: 0, Sigma: 1, Src: rand.NewPCG(seed, seed)}.Rand(). Each such call copies the distribution (distuv methods have value receivers) and, internally, does rand.New(src) to build a fresh math/rand/v2.Rand wrapper — and for the compound distributions it also binds method values (rnd.Float64, rnd.NormFloat64, …) that are then called indirectly. gonum’s math/rand/v2 backing means the wrapper does not escape and so is not heap allocated, but the copy, the construction, and the indirection are all measurable in a per-element, per-step hot loop. A Sampler owns one *math/rand/v2.Rand and calls its methods directly, so all of that overhead disappears.

Mathematical Background: Each method reproduces the exact algorithm the corresponding distuv distribution uses, consuming the underlying source in the same order, so for a given seed it yields the identical stream (not merely the same distribution). The compound draws mirror gonum’s choices directly:

Scope: Only the distributions where owning the generator is a clean, strict win live here. Binomial (a three-branch algorithm used in a single observation process) and Categorical (a stateful precomputed sampling heap) stay on distuv: the copied-algorithm maintenance cost outweighs the small per-draw saving, and neither sits in a tight per-element loop.

Usage Patterns:

Concurrency: A Sampler is NOT safe for concurrent use by multiple goroutines. This matches the engine’s per-partition model: each partition owns its own iteration and therefore its own Sampler, and partitions never share one.

Index

type Sampler

Sampler is an allocation-free source of random samples backed by a single owned math/rand/v2.Rand.

type Sampler struct {
    // contains filtered or unexported fields
}

func New

func New(seed uint64) *Sampler

New returns a Sampler seeded deterministically from seed. It reproduces the source the iterations handed to distuv (rand.NewPCG(seed, seed)), so New(seed) yields a stream identical to a distuv distribution built with Src: rand.NewPCG(seed, seed).

func NewFromSource

func NewFromSource(src rand.Source) *Sampler

NewFromSource returns a Sampler drawing from src. Use it to reproduce iterations that derive a distribution’s source from a master generator (e.g. rand.NewPCG(r.IntN(1e8), r.IntN(1e8))) rather than directly from the partition seed: wrap the same source and the stream is unchanged.

func (*Sampler) Beta

func (s *Sampler) Beta(alpha, beta float64) float64

Beta returns a Beta(alpha, beta) sample — identical to distuv.Beta{Alpha: alpha, Beta: beta, Src: …}.Rand(): the ratio ga/(ga+gb) of two Gamma(·, 1) draws taken in order from this Sampler’s stream.

func (*Sampler) Exponential

func (s *Sampler) Exponential(rate float64) float64

Exponential returns an Exponential(rate) sample — identical to distuv.Exponential{Rate: rate, Src: …}.Rand() (ExpFloat64()/rate form).

func (*Sampler) Float64

func (s *Sampler) Float64() float64

Float64 returns a uniform sample in [0,1) — identical to distuv.Uniform{Min: 0, Max: 1, Src: …}.Rand().

func (*Sampler) Gamma

func (s *Sampler) Gamma(alpha, beta float64) float64

Gamma returns a Gamma(alpha, beta) sample (shape alpha, rate beta) — identical to distuv.Gamma{Alpha: alpha, Beta: beta, Src: …}.Rand(), reproducing its exact branch structure and draw order: exponential for alpha==1, the Liu–Martin–Syring log-space method for alpha<0.2, and Marsaglia–Tsang otherwise (with the alpha<1 boost). Panics on beta<=0 or alpha<=0, matching distuv.

func (*Sampler) NormFloat64

func (s *Sampler) NormFloat64() float64

NormFloat64 returns a standard-normal sample — identical to distuv.Normal{Mu: 0, Sigma: 1, Src: …}.Rand().

func (*Sampler) Normal

func (s *Sampler) Normal(mu, sigma float64) float64

Normal returns a Normal(mu, sigma) sample — identical to distuv.Normal{Mu: mu, Sigma: sigma, Src: …}.Rand() (rnd*sigma+mu form).

func (*Sampler) Poisson

func (s *Sampler) Poisson(lambda float64) float64

Poisson returns a Poisson(lambda) sample — identical to distuv.Poisson{Lambda: lambda, Src: …}.Rand(): the direct exponential-interarrival method for lambda<10, and Hörmann’s PTRS transformed-rejection method for lambda>=10.

func (*Sampler) Rand

func (s *Sampler) Rand() *rand.Rand

Rand returns the owned generator, for the rare caller that needs a *rand.Rand directly (e.g. to derive further sources). Draws taken from it advance the same stream.

func (*Sampler) Uniform

func (s *Sampler) Uniform(min, max float64) float64

Uniform returns a uniform sample in [min,max) — identical to distuv.Uniform{Min: min, Max: max, Src: …}.Rand() (same rnd*(max-min)+min form, so bit-identical, not merely equal in distribution).

Generated by gomarkdoc