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 (in Prowl.Vector) implements the xoshiro256** algorithm, providing uniform, Gaussian, and geometry-specific random number generation. It supports both a convenient RNG.Shared static instance and seeded instances for fully reproducible results. All range methods are inclusive of both bounds.

Construction

// Time-seeded (non-reproducible) — different every run
var rng = new RNG();

// Seeded with a ulong — fully reproducible
var seeded = new RNG(42UL);

// Seeded with an int — convenience overload, cast to ulong internally
var seededInt = new RNG(12345);
ConstructorSeed typeDescription
new RNG()Time-basedUses Environment.TickCount ^ DateTime.UtcNow.Ticks.
new RNG(ulong seed)ulongDeterministic. State is bootstrapped via SplitMix64.
new RNG(int seed)intConvenience wrapper — casts seed to ulong.

RNG.Shared

// Global, lazily-initialized, time-seeded instance
float value = RNG.Shared.NextFloat();
RNG.Shared is a static readonly property. It is convenient for fire-and-forget calls where reproducibility is not required, but is not thread-safe — create per-thread instances for concurrent workloads.

Seed Management

var rng = new RNG();
rng.SetSeed(99999UL); // re-initialise the generator with a new seed
SetSeed(ulong seed) reinitialises all four 64-bit state words using the SplitMix64 algorithm, guaranteeing that two RNG instances with the same seed produce identical sequences.

Basic Value Generation

MethodReturnRangeDescription
NextFloat()float[0, 1]Uses the upper 24 bits for single-precision quality.
NextDouble()double[0, 1]Uses the upper 53 bits for full double-precision quality.
NextInt()int[0, int.MaxValue]Non-negative random integer.
NextUInt()uint[0, uint.MaxValue]Full 32-bit unsigned integer.
NextLong()long[0, long.MaxValue]Non-negative 64-bit integer.
NextBool()booltrue / falseSamples the least-significant bit of the raw output.

Range Methods

All Range overloads are inclusive on both ends.
int    n = rng.Range(0, 10);         // one of {0, 1, 2, …, 10}
float  f = rng.Range(0f, 1f);        // [0.0, 1.0]
double d = rng.Range(-1.0, 1.0);     // [-1.0, 1.0]
uint   u = rng.Range(5u, 20u);       // [5, 20]
long   l = rng.Range(0L, 100L);      // [0, 100]
Vector overloads generate per-component random values in the given range:
Float2 v2 = rng.Range(new Float2(0f, 0f), new Float2(10f, 5f));
Float3 v3 = rng.Range(new Float3(-1f), new Float3(1f));
Float4 v4 = rng.Range(Float4.Zero, Float4.One);

// Double variants also available:
Double3 dv = rng.Range(new Double3(-1.0), new Double3(1.0));

Vector Helpers

Generate random vectors with all components in [0, 1]:
Float2  f2 = rng.NextFloat2();
Float3  f3 = rng.NextFloat3();
Float4  f4 = rng.NextFloat4();
Double2 d2 = rng.NextDouble2();
Double3 d3 = rng.NextDouble3();
Double4 d4 = rng.NextDouble4();

Geometric Helpers

MethodReturnDescription
OnUnitCircle()Float2Uniformly distributed point on the unit circle (normalized 2D direction).
InsideUnitCircle()Float2Uniformly distributed point inside the unit disk. Uses sqrt of radius for area uniformity.
OnUnitSphere()Float3Uniformly distributed point on the unit sphere surface. Uses the spherical coordinate method.
InsideUnitSphere()Float3Uniformly distributed point inside the unit sphere. Uses cube-root of radius for volume uniformity.
Direction2D()Float2Alias for OnUnitCircle().
Direction3D()Float3Alias for OnUnitSphere().
NextAngle()floatRandom angle in radians, range [0, 2π].
NextAngleDegrees()floatRandom angle in degrees, range [0, 360].
AngleRange(float min, float max)floatRandom angle in [minRadians, maxRadians].
Float2 dir2D = rng.OnUnitCircle();      // random 2D direction
Float3 dir3D = rng.OnUnitSphere();      // random 3D direction
Float3 pos   = rng.InsideUnitSphere();  // random point inside a unit sphere

Color Generation

MethodReturnDescription
NextColor()Float4Random RGBA color with RGB in [0, 1] and alpha fixed at 1.
NextColor(float alpha)Float4Random RGB with a specified alpha.
NextColorWithAlpha()Float4Random RGBA with all four components randomised.
NextColorHSV(Float2 hueRange, Float2 saturationRange, Float2 valueRange)Float4Random color sampled from constrained HSV ranges, converted to RGBA.
Float4 randomColor    = rng.NextColor();               // fully opaque random
Float4 semiTransp     = rng.NextColor(0.5f);           // 50% alpha
Float4 coolBlueish    = rng.NextColorHSV(
    new Float2(0.55f, 0.70f),  // hue:   blue-cyan
    new Float2(0.6f, 1.0f),    // sat:   vivid
    new Float2(0.5f, 1.0f)     // value: bright
);

Gaussian Distribution

public float NextGaussian(float mean = 0.0f, float standardDeviation = 1.0f)
Uses the Box-Muller transform, which converts two uniform samples into two independent standard-normal values. The second value is cached internally so that consecutive calls reuse it, halving the average cost per sample.
// Weapon spread: mostly accurate shots, occasional outlier
float spreadAngle = rng.NextGaussian(mean: 0f, standardDeviation: 0.03f);

// AI reaction time: average 250 ms, std dev 40 ms
float reactionMs = rng.NextGaussian(mean: 250f, standardDeviation: 40f);
There is also an exponential distribution helper:
public float NextExponential(float lambda = 1.0f)
Returns a value from an exponential distribution with rate parameter lambda (mean = 1/lambda). Useful for modelling time-between-events in Poisson processes.

Probability Helpers

MethodDescription
Chance(float probability)Returns true with the given probability in [0, 1].
Chance(double probability)double overload.
WeightedChoice(float[] weights)Returns the index of a randomly selected element, weighted by the values in weights. Throws if all weights are zero.
if (rng.Chance(0.05f))
    SpawnRareLoot(); // 5% chance

int lootTier = rng.WeightedChoice(new float[] { 60f, 25f, 10f, 4f, 1f });
// 60% common, 25% uncommon, 10% rare, 4% epic, 1% legendary

Collections — Shuffle and Choose

// Pick a random element from an array
T item = rng.Choice(array);

// Shuffle an array in-place (Fisher-Yates)
rng.Shuffle(array);

// Return a shuffled copy, leaving the original intact
T[] shuffledCopy = rng.Shuffled(array);
Shuffle<T> implements the unbiased Fisher-Yates algorithm with O(n) complexity. Shuffled<T> performs a full copy first, then shuffles the copy.

Utility

// Fill a byte array with random data
byte[] buffer = new byte[32];
rng.NextBytes(buffer);

// Random alphanumeric string (default charset: A-Z a-z 0-9)
string token = rng.NextString(16);

// Custom charset
string hex = rng.NextString(8, "0123456789ABCDEF");

Code Example — Reproducible Procedural Generation

using Prowl.Vector;

// Seeded RNG for a deterministic dungeon layout.
// Every run with seed 42 produces the same dungeon.
var rng = new RNG(42UL);

const int RoomCount = 10;
var rooms = new Float3[RoomCount];

for (int i = 0; i < RoomCount; i++)
{
    // Room centres spread across a 100×100×10 volume
    rooms[i] = rng.Range(new Float3(0f, 0f, 0f), new Float3(100f, 100f, 10f));
}

// Shuffle the room connection order reproducibly
int[] order = new int[RoomCount];
for (int i = 0; i < RoomCount; i++) order[i] = i;
rng.Shuffle(order);

// Random enemy count per room, Gaussian-distributed around 3
for (int i = 0; i < RoomCount; i++)
{
    int enemies = Maths.Max(0, Maths.RoundToInt(rng.NextGaussian(mean: 3f, standardDeviation: 1.5f)));
    Console.WriteLine($"Room {order[i]}: {enemies} enemies at {rooms[i]}");
}
Use RNG.Shared for one-off calls where reproducibility does not matter. Use new RNG(seed) — storing and reusing the same ulong seed — whenever you need deterministic output that survives a restart, a level reload, or a network sync.

Build docs developers (and LLMs) love