A PCG pseudorandom number generator implementation for .NET and Fable. PCG is a family of simple fast space-efficient statistically good algorithms for random number generation.
See the PCG website and paper for more information.
Add the NuGet package to your project:
dotnet add package Zanaptak.PcgRandom
The main general-purpose generator is Pcg
, which is compatible with System.Random. It uses an internal PCG 32-bit unsigned integer generator to produce signed integer output.
using Zanaptak.PcgRandom;
var pcg = new Pcg(); // or with seed: Pcg(12345)
var randomValue = pcg.Next();
var diceRoll = pcg.Next(1, 7);
var coinFlip = pcg.NextBoolean();
Console.WriteLine($"{randomValue}, {diceRoll}, {coinFlip}");
open Zanaptak.PcgRandom
let pcg = Pcg() // or with seed: Pcg(12345)
let randomValue = pcg.Next()
let diceRoll = pcg.Next(1, 7)
let coinFlip = pcg.NextBoolean()
printfn $"{randomValue}, {diceRoll}, {coinFlip}"
Additional Pcg*
generators with multiple algorithm variants are available for 8-, 16-, 32-, 64-, and 128-bit unsigned integer output sizes. By default, these use the recommended variants from the PCG paper, with options to specify other variants.
using Zanaptak.PcgRandom;
using Pcg128Variants = Zanaptak.PcgRandom.Pcg128Variants;
// generates Byte
var pcg8 = new Pcg8();
var randomByte = pcg8.Next();
// generates unsigned 128-bit integer as BigInteger,
// using variant, seed, and stream parameters
var pcg128 = new Pcg128(Pcg128Variants.Invertible.RXS_M_XS, 12345, 67890);
var randomBigint = pcg128.Next();
Console.WriteLine($"{randomByte}, {randomBigint}");
open Zanaptak.PcgRandom
// generates Byte
let pcg8 = Pcg8()
let randomByte = pcg8.Next()
// generates unsigned 128-bit integer as BigInteger,
// using variant, seed, and stream parameters
let pcg128 = Pcg128(Pcg128Variants.Invertible.RXS_M_XS, 12345I, 67890I)
let randomBigint = pcg128.Next()
printfn $"{randomByte}, {randomBigint}"
The different algorithm variants and output functions defined by the PCG library are available via overloaded constructors taking a variant parameter.
The overall categories of variants are:
Normal
: General purpose variant balancing speed and statistical quality. Allows stream selection. Based on LCG generator type.Fast
: Faster variant but with reduced statistical quality. Based on MCG generator type.Invertible
: Variant with the same number of outbut bits as internal state bits. Easier to reverse-engineer internal state than other variants.
A Pcg128
generator is available only as an Invertible variant; there are no Normal or Fast variants (which would require 256 bits of state) defined in the PCG source material. Since there is no Normal variant to serve as a default, there is intentionally no parameterless Pcg128()
constructor; an Invertible variant must be specified.
Please refer the PCG website and paper for further details.
The generator constructors can optionally take a seed
parameter, and for some variants, a stream
parameter. The seed specifies the initial internal state of the generator. The stream specifies the increment, which is part of the internal step calculation that advances the generator to each new state when generating values. Identical generators initialized with the same seed and stream will produce the same output sequence. If not specified, the seed will be randomly generated, and the stream will be set to a predefined default value from the PCG reference C implementation. (Note that for the stream value, the high bit is discarded; e.g. for 64-bit seed/stream parameters, there are 264 possible seeds and 263 possible streams.)
See the benchmark project.
-
This implementation is based on the PCG reference C implementation, which is available under the MIT License.
-
Variants that use 128 bit arithmetic are much slower than other variants because they use
System.Numerics.BigInteger
instead of primitive integer types. These can be identified by their constructors takingBigInteger
seed values; they includePcg64Variants.Normal
,Pcg64Variants.Fast
, andPcg128Variants.Invertible
. -
These generators use internal mutable state and do not implement any thread safety mechanisms.