Initial
This commit is contained in:
parent
cde75c557d
commit
9eda579197
36
FastRng/Distributions/Exponential.cs
Normal file
36
FastRng/Distributions/Exponential.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastRng.Distributions
|
||||
{
|
||||
public sealed class Exponential : IDistribution
|
||||
{
|
||||
private double mean = 1;
|
||||
|
||||
public IRandom Random { get; set; }
|
||||
|
||||
public double Mean
|
||||
{
|
||||
get => this.mean;
|
||||
set
|
||||
{
|
||||
if(value <= 0)
|
||||
throw new ArgumentOutOfRangeException(message: "Mean must be greater than 0", null);
|
||||
|
||||
this.mean = value;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<double> GetDistributedValue(CancellationToken token)
|
||||
{
|
||||
if (this.Random == null)
|
||||
return 0;
|
||||
|
||||
if(this.Mean == 1)
|
||||
return -Math.Log(await this.Random.GetUniformDouble(token));
|
||||
else
|
||||
return this.Mean * -Math.Log(await this.Random.GetUniformDouble(token));
|
||||
}
|
||||
}
|
||||
}
|
69
FastRng/Distributions/Gamma.cs
Normal file
69
FastRng/Distributions/Gamma.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastRng.Distributions
|
||||
{
|
||||
public sealed class Gamma : IDistribution
|
||||
{
|
||||
private double shape = 1;
|
||||
|
||||
public IRandom Random { get; set; }
|
||||
|
||||
public double Shape
|
||||
{
|
||||
get => this.shape;
|
||||
set
|
||||
{
|
||||
if(value <= 0)
|
||||
throw new ArgumentOutOfRangeException(message: "Shape must be greater than 0", null);
|
||||
|
||||
this.shape = value;
|
||||
}
|
||||
}
|
||||
|
||||
public double Scale { get; set; } = 1;
|
||||
|
||||
public async Task<double> GetDistributedValue(CancellationToken token)
|
||||
{
|
||||
if (this.Random == null)
|
||||
return 0;
|
||||
|
||||
// Implementation based on "A Simple Method for Generating Gamma Variables"
|
||||
// by George Marsaglia and Wai Wan Tsang. ACM Transactions on Mathematical Software
|
||||
// Vol 26, No 3, September 2000, pages 363-372.
|
||||
|
||||
if (shape >= 1.0)
|
||||
{
|
||||
var distNormal = new Normal();
|
||||
var d = shape - 1.0 / 3.0;
|
||||
var c = 1.0 / Math.Sqrt(9.0 * d);
|
||||
while(true)
|
||||
{
|
||||
double x, v;
|
||||
do
|
||||
{
|
||||
x = await this.Random.NextNumber(0, 1, distNormal, token);
|
||||
v = 1.0 + c * x;
|
||||
}
|
||||
while (v <= 0.0);
|
||||
|
||||
v = v * v * v;
|
||||
var u = await this.Random.GetUniformDouble(token);
|
||||
var xSquared = x * x;
|
||||
|
||||
if (u < 1.0 - 0.0331 * xSquared * xSquared || Math.Log(u) < 0.5 * xSquared + d * (1.0 - v + Math.Log(v)))
|
||||
return this.Scale * d * v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var dist = new Gamma{ Scale = 1, Shape = 1 + this.Shape};
|
||||
|
||||
var g = await this.Random.NextNumber(0.0f, 1.0f, dist, token); // TODO: Use double
|
||||
var w = await this.Random.GetUniformDouble(token);
|
||||
return this.Scale * g * Math.Pow(w, 1.0 / this.Shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
FastRng/Distributions/Normal.cs
Normal file
41
FastRng/Distributions/Normal.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastRng.Distributions
|
||||
{
|
||||
public sealed class Normal : IDistribution
|
||||
{
|
||||
private double standardDeviation = 1;
|
||||
|
||||
public IRandom Random { get; set; }
|
||||
|
||||
public double Mean { get; set; } = 0;
|
||||
|
||||
public double StandardDeviation
|
||||
{
|
||||
get => this.standardDeviation;
|
||||
set
|
||||
{
|
||||
if(value <= 0)
|
||||
throw new ArgumentOutOfRangeException(message: "Standard deviation must be greater than 0", null);
|
||||
|
||||
this.standardDeviation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<double> GetDistributedValue(CancellationToken token = default)
|
||||
{
|
||||
if (this.Random == null)
|
||||
return 0;
|
||||
|
||||
var u1 = await this.Random.GetUniformDouble(token);
|
||||
var u2 = await this.Random.GetUniformDouble(token);
|
||||
var r = Math.Sqrt(-2.0 * Math.Log(u1));
|
||||
var theta = 2.0 * Math.PI * u2;
|
||||
var value = r * Math.Sin(theta);
|
||||
|
||||
return this.Mean + this.StandardDeviation * value;
|
||||
}
|
||||
}
|
||||
}
|
12
FastRng/Distributions/Uniform.cs
Normal file
12
FastRng/Distributions/Uniform.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastRng.Distributions
|
||||
{
|
||||
public sealed class Uniform : IDistribution
|
||||
{
|
||||
public IRandom Random { get; set; }
|
||||
|
||||
public async Task<double> GetDistributedValue(CancellationToken token = default) => this.Random == null ? 0 : await this.Random.GetUniformDouble(token);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user