58 lines
2.2 KiB
C#
58 lines
2.2 KiB
C#
using System;
|
|
using System.Numerics;
|
|
using System.Threading;
|
|
|
|
namespace FastRng.Distributions;
|
|
|
|
public sealed class Uniform<TNum> : IDistribution<TNum> where TNum : IFloatingPointIeee754<TNum>
|
|
{
|
|
private readonly IRandom<TNum> rng;
|
|
|
|
public Uniform(IRandom<TNum> rng)
|
|
{
|
|
this.rng = rng ?? throw new ArgumentNullException(nameof(rng), "An IRandom<TNum> implementation is needed.");
|
|
}
|
|
|
|
public TNum GetDistributedValue(CancellationToken token = default) => this.rng.GetUniform(token);
|
|
|
|
public uint NextNumber(uint rangeStart, uint rangeEnd, CancellationToken cancel = default)
|
|
{
|
|
// Swap the values if the range start is greater than the range end:
|
|
if (rangeStart > rangeEnd)
|
|
(rangeStart, rangeEnd) = (rangeEnd, rangeStart);
|
|
|
|
var range = rangeEnd - rangeStart;
|
|
var distributedValue = this.GetDistributedValue(cancel);
|
|
return (uint) ((float.CreateChecked(distributedValue) * range) + rangeStart);
|
|
}
|
|
|
|
public ulong NextNumber(ulong rangeStart, ulong rangeEnd, CancellationToken cancel = default)
|
|
{
|
|
// Swap the values if the range start is greater than the range end:
|
|
if (rangeStart > rangeEnd)
|
|
(rangeStart, rangeEnd) = (rangeEnd, rangeStart);
|
|
|
|
var range = rangeEnd - rangeStart;
|
|
var distributedValue = this.GetDistributedValue(cancel);
|
|
return (ulong) ((double.CreateChecked(distributedValue) * range) + rangeStart);
|
|
}
|
|
|
|
public TNum NextNumber(TNum rangeStart, TNum rangeEnd, CancellationToken cancel = default)
|
|
{
|
|
// Swap the values if the range start is greater than the range end:
|
|
if (rangeStart > rangeEnd)
|
|
(rangeStart, rangeEnd) = (rangeEnd, rangeStart);
|
|
|
|
var range = rangeEnd - rangeStart;
|
|
var distributedValue = this.GetDistributedValue(cancel);
|
|
return (distributedValue * range) + rangeStart;
|
|
}
|
|
|
|
public TNum NextNumber(CancellationToken cancel = default) => this.NextNumber(TNum.Zero, TNum.One, cancel);
|
|
|
|
public bool HasDecisionBeenMade(TNum above, TNum below, CancellationToken cancel = default)
|
|
{
|
|
var number = this.NextNumber(cancel);
|
|
return number > above && number < below;
|
|
}
|
|
} |