FastRng/FastRng/Distributions/Uniform.cs

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;
}
}