Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ProwlEngine/Prowl.Vector/llms.txt

Use this file to discover all available pages before exploring further.

RNG is a high-quality, non-cryptographic pseudo-random number generator in the Prowl.Vector namespace, based on the xoshiro256** algorithm by David Blackman and Sebastiano Vigna. It provides a broad API covering basic numeric types, vector types, geometric sampling, Gaussian and exponential distributions, collections, and color generation. All range methods are inclusive of both endpoints.

Declaration

public class RNG

Algorithm

xoshiro256** (by David Blackman and Sebastiano Vigna) uses a 256-bit state (four ulong values) and applies a star-star scrambler on output. It has:
  • Period: 2²⁵⁶ − 1
  • Speed: extremely fast (no division in the hot path)
  • Quality: passes all known statistical tests (BigCrush, PractRand)
The initial state is derived from a single seed using SplitMix64, which ensures good avalanche even from zero or low-entropy seeds.

Static Members

Shared

public static RNG Shared { get; }
A global, lazily initialized shared RNG instance seeded from the current time. Convenient for one-off calls; not thread-safe for concurrent access. Create separate RNG instances per thread for parallel workloads.

Constructors

Time-seeded (default)

public RNG()
Seeds using Environment.TickCount ^ DateTime.UtcNow.Ticks, providing a unique sequence on each run.

From a ulong seed

public RNG(ulong seed)
Produces a deterministic, reproducible sequence for the given seed.

From an int seed

public RNG(int seed)
Casts seed to ulong and delegates to the ulong constructor.

Seed Management

SetSeed

public void SetSeed(ulong seed)
Re-initializes the generator’s 256-bit state from a single seed via SplitMix64. Calling this resets the sequence to the beginning.

Basic Generation

NextFloat

public float NextFloat()
Returns a random float in [0, 1] (inclusive). Uses the upper 24 bits of the raw output for full single-precision mantissa coverage.

NextDouble

public double NextDouble()
Returns a random double in [0, 1] (inclusive). Uses the upper 53 bits for full double-precision mantissa coverage.

NextInt

public int NextInt()
Returns a random int in [0, int.MaxValue].

NextUInt

public uint NextUInt()
Returns a random uint in [0, uint.MaxValue].

NextLong

public long NextLong()
Returns a random long in [0, long.MaxValue].

NextBool

public bool NextBool()
Returns true or false with equal probability (tests the least-significant bit of the raw output).

Range Methods

All range methods are inclusive of both min and max.

Scalar ranges

public float  Range(float min, float max)
public double Range(double min, double max)
public int    Range(int min, int max)
public uint   Range(uint min, uint max)
public long   Range(long min, long max)
  • Integer overloads use rejection sampling to eliminate modulo bias.
  • Float/double overloads scale Next*() linearly: min + Next*() * (max - min).

Vector ranges

public Float2  Range(Float2 min, Float2 max)
public Float3  Range(Float3 min, Float3 max)
public Float4  Range(Float4 min, Float4 max)

public Double2 Range(Double2 min, Double2 max)
public Double3 Range(Double3 min, Double3 max)
public Double4 Range(Double4 min, Double4 max)
Each component is sampled independently in its respective [min, max] range.

Vector Helpers

NextFloat2 / NextFloat3 / NextFloat4

public Float2 NextFloat2()
public Float3 NextFloat3()
public Float4 NextFloat4()
Returns a random vector with all components in [0, 1].

NextDouble2 / NextDouble3 / NextDouble4

public Double2 NextDouble2()
public Double3 NextDouble3()
public Double4 NextDouble4()
Returns a random double-precision vector with all components in [0, 1].

Geometry Helpers

OnUnitCircle

public Float2 OnUnitCircle()
Returns a uniformly distributed random point on the unit circle (magnitude = 1). Uses a random angle via cos/sin.

InsideUnitCircle

public Float2 InsideUnitCircle()
Returns a uniformly distributed random point inside the unit circle (magnitude ≤ 1). Uses square-root scaling of the radius to correct for the non-uniform naïve approach.

OnUnitSphere

public Float3 OnUnitSphere()
Returns a uniformly distributed random point on the surface of the unit sphere. Uses the spherical coordinate method with Acos(2v − 1) for uniform area distribution.

InsideUnitSphere

public Float3 InsideUnitSphere()
Returns a uniformly distributed random point inside the unit sphere volume. Scales a surface point by u^(1/3) (cube-root) for correct volumetric density.

Direction2D / Direction3D

public Float2 Direction2D()   // alias for OnUnitCircle
public Float3 Direction3D()   // alias for OnUnitSphere
Convenience aliases that return normalized random direction vectors.

Angle Helpers

public float NextAngle()               // [0, 2π) in radians
public float NextAngleDegrees()        // [0, 360) in degrees
public float AngleRange(float minRad, float maxRad)

Color Generation

NextColor

public Float4 NextColor()
public Float4 NextColor(float alpha)
Returns a random RGBA color as Float4. The first overload always sets alpha = 1.0. All RGB components are uniformly sampled in [0, 1].

NextColorWithAlpha

public Float4 NextColorWithAlpha()
Returns a random Float4 with all four components (RGBA) uniformly sampled in [0, 1].

NextColorHSV

public Float4 NextColorHSV(Float2 hueRange, Float2 saturationRange, Float2 valueRange)
Generates a random color in HSV space and converts to RGB. Each range is a Float2(min, max) where values are in [0, 1].
ParameterDescription
hueRangeHue range — (0, 1) covers the full spectrum.
saturationRangeSaturation range — (1, 1) for fully saturated colors.
valueRangeValue (brightness) range — (0.5, 1) for medium to bright colors.

Probability & Weighted Selection

Chance

public bool Chance(float probability)
public bool Chance(double probability)
Returns true with the given probability in [0, 1]. Example: Chance(0.25f) is true 25% of the time.

WeightedChoice

public int WeightedChoice(float[] weights)
Selects an index from weights with probability proportional to each weight. Throws ArgumentException if weights are null, empty, all zero, or contain negative values.

Collections

Choice<T>

public T Choice<T>(T[] array)
Returns a uniformly random element from array. Throws ArgumentException if the array is null or empty.

Shuffle<T>

public void Shuffle<T>(T[] array)
Shuffles array in place using the Fisher-Yates algorithm (O(n), unbiased).

Shuffled<T>

public T[] Shuffled<T>(T[] array)
Returns a new shuffled copy of array. The original is not modified.

Statistical Distributions

NextGaussian

public float NextGaussian(float mean = 0.0f, float standardDeviation = 1.0f)
Returns a sample from a Gaussian (normal) distribution using the Box-Muller transform. Both outputs of each pair are cached, so every other call returns the cached second value — no extra cost on average.
ParameterDefaultDescription
mean0.0Mean (center) of the distribution.
standardDeviation1.0Standard deviation (spread).

NextExponential

public float NextExponential(float lambda = 1.0f)
Returns a sample from an exponential distribution. lambda is the rate parameter (must be > 0). The mean of the distribution is 1 / lambda.

Utility

NextBytes

public void NextBytes(byte[] bytes)
Fills bytes with random data in chunks of 8 bytes using the raw ulong output.

NextString

public string NextString(int length, string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
Returns a random string of length characters drawn from charset. Returns an empty string when length ≤ 0.

Code Example

using Prowl.Vector;

// --- Reproducible seeded generation ---
var rng = new RNG(42uL);

float   f  = rng.NextFloat();             // [0, 1]
double  d  = rng.NextDouble();            // [0, 1]
int     i  = rng.Range(1, 6);            // dice roll [1, 6]
bool    b  = rng.NextBool();

Float3  dir = rng.OnUnitSphere();         // random direction
Float3  pt  = rng.InsideUnitSphere() * 5f; // point in sphere of radius 5

// --- Gaussian noise for procedural shake ---
float shakeMagnitude = 0.1f;
Float3 cameraOffset = new Float3(
    rng.NextGaussian(0f, shakeMagnitude),
    rng.NextGaussian(0f, shakeMagnitude),
    0f
);

// --- Weighted loot table ---
float[] weights = { 60f, 25f, 10f, 5f };   // common/uncommon/rare/legendary
int tier = rng.WeightedChoice(weights);

// --- Shuffle a deck of cards ---
int[] deck = new int[52];
for (int c = 0; c < 52; c++) deck[c] = c;
rng.Shuffle(deck);

// --- Tileable random color palette ---
var palette = new Float4[8];
for (int p = 0; p < palette.Length; p++)
    palette[p] = rng.NextColorHSV(
        hueRange:        new Float2(0f, 1f),
        saturationRange: new Float2(0.7f, 1f),
        valueRange:      new Float2(0.6f, 1f)
    );

// --- Shared instance for quick use ---
float quickRandom = RNG.Shared.NextFloat();

// --- Re-seed for a new deterministic run ---
rng.SetSeed(12345uL);
float sameAsFirst = rng.NextFloat(); // identical to the value produced from seed 12345

Notes

  • RNG is a class (reference type). Multiple variables can reference the same instance.
  • RNG.Shared is not thread-safe. Use a per-thread RNG instance for concurrent code: [ThreadStatic] private static RNG _threadRng = new RNG();
  • The NextGaussian implementation caches one value between calls. Do not use the same RNG instance from two threads without a lock, or the cached Gaussian value can be lost.
  • For cryptographically secure random bytes, use System.Security.Cryptography.RandomNumberGenerator instead.
  • All integer Range methods use rejection sampling to guarantee exact uniform distribution with no modulo bias.

Build docs developers (and LLMs) love