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