Prior art in "standard" libraries
Go
Golang has two APIs, one for non-crypto PRNGs and one for cryptographically random bytes:
Rust
Rust has a family of packages for PRNGs. The basic interfaces are defined in rand_core.
C++
The C++ standard defines a set of highly templated classes which together form the PRNG API.
O'Neill makes the point that this API is flexible, but hard to use correctly, and proposes an alternative interface. IMO it's a nice API that provides safe defaults but is still very flexible for those who want flexibility.
numpy.random
Inspired by O'Neill.
Prior art in Haskell libraries
splitmix
Pure, splittable SplitMix implementation.
mwc-random
Provides a monadic generator interface for Marsaglia's MWC256 (a.k.a. MWC8222) multiply-with-carry generator, a way to access system randomness, and a way to draw from a number of random distributions. Does not provide a way to split/spawn generators or seeds.
random-source
Defines the MonadRandom typeclass, an interface for random number generation. One aim of our effort here should be to make random-source unnecessary (see #4 (comment)).
random-fu
Provides a way to draw from a number of random distributions. The randomness source is pluggable AFAICT.
tf-random
Implements a splittable PRNG implementing the old random's RandomGen, provides alternative interfaces, and a way to access system randomness. Based on ThreeFish.
More prior art
Common concepts
The API split between randomness sources and random distributions is apparent in every API I looked at:
Note that drawing from a distribution is what random-fu exists for in the Haskell world. I believe it is worth understanding if and what changes would be required to make random-fu work with the new random. Apart from that, it seems to cover the issue of drawing from a distribution well, so we can concentrate on building a solid API for randomness sources and seeding here.
Seeding
Seeding is handled a bit differently from API to API.
- Rust's
rand has the SeedableRng trait, whose associated Seed type must be convertible to byte slices.
RNGs can be seeded directly, from an integer value (which is mixed to increase entropy), or from another RNG (which appropriate warnings in the docs).
- C++ has
random_device to get randomness from the system and seed_seq to generate good seeds from low-entropy inputs, which can be used to instantiate randum number "engines" like the Mersenne Twister.
- numpy works similarly to C++, where the relevant class is called
SeedSequence, but with a nicer API and fewer footguns.
- Go has the
Rand.Seed function.
Prior art in "standard" libraries
Go
Golang has two APIs, one for non-crypto PRNGs and one for cryptographically random bytes:
Rust
Rust has a family of packages for PRNGs. The basic interfaces are defined in
rand_core.C++
The C++ standard defines a set of highly templated classes which together form the PRNG API.
O'Neill makes the point that this API is flexible, but hard to use correctly, and proposes an alternative interface. IMO it's a nice API that provides safe defaults but is still very flexible for those who want flexibility.
numpy.random
Inspired by O'Neill.
Prior art in Haskell libraries
splitmixPure, splittable SplitMix implementation.
mwc-randomProvides a monadic generator interface for Marsaglia's MWC256 (a.k.a. MWC8222) multiply-with-carry generator, a way to access system randomness, and a way to draw from a number of random distributions. Does not provide a way to split/spawn generators or seeds.
random-sourceDefines the
MonadRandomtypeclass, an interface for random number generation. One aim of our effort here should be to makerandom-sourceunnecessary (see #4 (comment)).random-fuProvides a way to draw from a number of random distributions. The randomness source is pluggable AFAICT.
tf-randomImplements a splittable PRNG implementing the old
random'sRandomGen, provides alternative interfaces, and a way to access system randomness. Based on ThreeFish.More prior art
Common concepts
The API split between randomness sources and random distributions is apparent in every API I looked at:
Sourcein Go,RngCoreandRng(automatically derived fromRngCore) in Rust,UniformRandomBitGeneratorin C++,BitGeneratorin numpy. These can be given a seed, and they generate random bits/bytes/words.Randin Go, implementors of theDistributiontrait in Rust, components implementingRandomNumberDistributionin C++,Generatorin numpy. These use a randomness source to draw from a distribution.Note that drawing from a distribution is what
random-fuexists for in the Haskell world. I believe it is worth understanding if and what changes would be required to makerandom-fuwork with the newrandom. Apart from that, it seems to cover the issue of drawing from a distribution well, so we can concentrate on building a solid API for randomness sources and seeding here.Seeding
Seeding is handled a bit differently from API to API.
randhas theSeedableRngtrait, whose associatedSeedtype must be convertible to byte slices.RNGs can be seeded directly, from an integer value (which is mixed to increase entropy), or from another RNG (which appropriate warnings in the docs).
random_deviceto get randomness from the system andseed_seqto generate good seeds from low-entropy inputs, which can be used to instantiate randum number "engines" like the Mersenne Twister.SeedSequence, but with a nicer API and fewer footguns.Rand.Seedfunction.