Refactored to use a shape fitter
This commit is contained in:
		
							parent
							
								
									f69330d79e
								
							
						
					
					
						commit
						25c773b411
					
				| @ -1,4 +1,5 @@ | |||||||
| using System; | using System; | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
| using System.Threading; | using System.Threading; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| 
 | 
 | ||||||
| @ -6,42 +7,38 @@ namespace FastRng.Double.Distributions | |||||||
| { | { | ||||||
|     public sealed class Normal : IDistribution |     public sealed class Normal : IDistribution | ||||||
|     { |     { | ||||||
|         private double standardDeviation = 1.0; |         private const double SQRT_2PI = 2.506628275; | ||||||
|  |         private const double STDDEV = 0.4; | ||||||
|  |         private const double MEAN = 0.5; | ||||||
|          |          | ||||||
|         public IRandom Random { get; set; } |         private ShapeFitter fitter; | ||||||
|  |         private IRandom random; | ||||||
| 
 | 
 | ||||||
|         public double Mean { get; set; } = 0.0; |         public Normal() | ||||||
| 
 |  | ||||||
|         public double StandardDeviation |  | ||||||
|         { |         { | ||||||
|             get => this.standardDeviation; |         } | ||||||
|  |          | ||||||
|  |         public IRandom Random | ||||||
|  |         { | ||||||
|  |             get => this.random; | ||||||
|             set |             set | ||||||
|             { |             { | ||||||
|                 if(value <= 0.0) |                 this.random = value; | ||||||
|                     throw new ArgumentOutOfRangeException(message: "Standard deviation must be greater than 0", null); |                 this.fitter = new ShapeFitter(ShapeFunction, this.random, 100, 0.99); | ||||||
|                  |  | ||||||
|                 this.standardDeviation = value; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         private static double ShapeFunction(double x) | ||||||
|  |         { | ||||||
|  |             return 1.0 / (STDDEV * SQRT_2PI) * Math.Exp(-Math.Pow((x - MEAN) / STDDEV, 2.0)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         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; | ||||||
| 
 | 
 | ||||||
|             // |             return await this.fitter.NextNumber(); // TODO: Add token! | ||||||
|             // Previously: |  | ||||||
|             // |  | ||||||
|             // var u1 = await this.Random.GetUniform(token); |  | ||||||
|             // var u2 = await this.Random.GetUniform(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; |  | ||||||
|              |  | ||||||
|             const double SQRT_2PI = 2.506628275; |  | ||||||
|             var x = await this.Random.GetUniform(token); // BUG: It seems, that uniform is not uniform (enough) or RunningStatistics had specific issues. Test, if Math.NET's uniform is better. |  | ||||||
|             return 1.0 / (this.StandardDeviation * SQRT_2PI) * Math.Exp(-0.5 * Math.Pow((x - this.Mean) / this.StandardDeviation, 2.0)); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user