pf_random_seed Function

public function pf_random_seed() result(s)

A fresh, nondeterministic seed, in [1, huge(int64)].

Folds the clock at its finest resolution together with a process-wide call counter, so two calls differ even when the clock has not ticked between them, and so do two calls racing on different threads -- the counter is incremented by an !$omp atomic capture, so no increment is lost and no two callers see the same count. (In a build without OpenMP that directive is a comment and the guarantee lapses; see the counter's declaration.) This is the one procedure in the module that is not a pure function, and the one that is deliberately not reproducible: a program that wants a reproducible run stores the value it got and passes that back next time.

Two calls can only collide if their mixer outputs differ in nothing but the bit the range restriction clears -- one specific partner per call out of 2**64, which no run will meet.

Not cryptographic, and not a substitute for one: the clock is guessable and the counter is small. For anything an adversary must not predict, take the seed from a CSPRNG instead.

Arguments

None

Return Value integer(kind=int64)

a nondeterministic seed in [1, huge(int64)]


Source Code

    function pf_random_seed() result(s)
        integer(int64) :: s                         !! a nondeterministic seed in `[1, huge(int64)]`
        integer(int64) :: counted, ticks, rate, ceiling_
        ! Fetch-and-add, which is exactly what this needs -- `atomic capture` is the precise
        ! construct for it and is lock-free, where the named critical region this replaced
        ! serialised every caller through a lock for a single integer update. See the counter's
        ! own declaration for what holds when OpenMP is absent.
        !$omp atomic capture
        seed_call_counter = seed_call_counter + 1_int64
        counted = seed_call_counter
        !$omp end atomic
        call system_clock(count=ticks, count_rate=rate, count_max=ceiling_)
        s = mix64(ieor(mix64(ieor(ticks, rate)), counted))
        s = ibclr(s, 63)                            ! into [0, huge]; the mixer is otherwise a bijection
        if (s == 0_int64) s = 1_int64
    end function pf_random_seed