Refactored to use shape fitter
This commit is contained in:
parent
243a4c044b
commit
9ea1b43b87
@ -6,47 +6,35 @@ namespace FastRng.Double.Distributions
|
|||||||
{
|
{
|
||||||
public sealed class Beta : IDistribution
|
public sealed class Beta : IDistribution
|
||||||
{
|
{
|
||||||
private double a = 1.0;
|
private const double ALPHA = 2;
|
||||||
private double b = 1.0;
|
private const double BETA = 2;
|
||||||
public IRandom Random { get; set; }
|
private const double CONSTANT = 4;
|
||||||
|
|
||||||
|
private ShapeFitter fitter;
|
||||||
|
private IRandom random;
|
||||||
|
|
||||||
public double A
|
public Beta()
|
||||||
{
|
{
|
||||||
get => this.a;
|
}
|
||||||
|
|
||||||
|
public IRandom Random
|
||||||
|
{
|
||||||
|
get => this.random;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if(value <= 0.0)
|
this.random = value;
|
||||||
throw new ArgumentOutOfRangeException(message: "Parameter must be greater than 0", null);
|
this.fitter = new ShapeFitter(Beta.ShapeFunction, this.random, 50, 0.99);
|
||||||
|
|
||||||
this.a = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double B
|
private static double ShapeFunction(double x) => CONSTANT * Math.Pow(x, ALPHA - 1) * Math.Pow(1 - x, BETA - 1);
|
||||||
{
|
|
||||||
get => this.b;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if(value <= 0.0)
|
|
||||||
throw new ArgumentOutOfRangeException(message: "Parameter must be greater than 0", null);
|
|
||||||
|
|
||||||
this.b = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async ValueTask<double> GetDistributedValue(CancellationToken token = default)
|
public async ValueTask<double> GetDistributedValue(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (this.Random == null)
|
if (this.Random == null)
|
||||||
return double.NaN;
|
return double.NaN;
|
||||||
|
|
||||||
// There are more efficient methods for generating beta samples.
|
return await this.fitter.NextNumber(token);
|
||||||
// However such methods are a little more efficient and much more complicated.
|
|
||||||
// For an explanation of why the following method works, see
|
|
||||||
// http://www.johndcook.com/distribution_chart.html#gamma_beta
|
|
||||||
|
|
||||||
var u = await this.Random.NextNumber(new Gamma{Shape = this.A, Scale = 1.0}, token);
|
|
||||||
var v = await this.Random.NextNumber(new Gamma{Shape = this.B, Scale = 1.0}, token);
|
|
||||||
return u / (u + v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user