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;
        }
    }
}