File size: 1,651 Bytes
05c9ac2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
using System;
namespace Unity.MLAgents.Inference.Utils
{
/// <summary>
/// RandomNormal - A random number generator that produces normally distributed random
/// numbers using the Marsaglia polar method:
/// https://en.wikipedia.org/wiki/Marsaglia_polar_method
/// TODO: worth overriding System.Random instead of aggregating?
/// </summary>
internal class RandomNormal
{
readonly double m_Mean;
readonly double m_Stddev;
readonly Random m_Random;
public RandomNormal(int seed, float mean = 0.0f, float stddev = 1.0f)
{
m_Mean = mean;
m_Stddev = stddev;
m_Random = new Random(seed);
}
// Each iteration produces two numbers. Hold one here for next call
bool m_HasSpare;
double m_SpareUnscaled;
/// <summary>
/// Return the next random double number.
/// </summary>
/// <returns>Next random double number.</returns>
public double NextDouble()
{
if (m_HasSpare)
{
m_HasSpare = false;
return m_SpareUnscaled * m_Stddev + m_Mean;
}
double u, v, s;
do
{
u = m_Random.NextDouble() * 2.0 - 1.0;
v = m_Random.NextDouble() * 2.0 - 1.0;
s = u * u + v * v;
}
while (s >= 1.0 || Math.Abs(s) < double.Epsilon);
s = Math.Sqrt(-2.0 * Math.Log(s) / s);
m_SpareUnscaled = u * s;
m_HasSpare = true;
return v * s * m_Stddev + m_Mean;
}
}
}
|