/// <summary> /// Get normal (Gaussian) random sample with mean 0 and standard deviation 1 /// </summary> /// <returns></returns> public static double GetNormal() { // Use Box-Muller algorithm double u1 = GenerateUniform.GetUniform(); double u2 = GenerateUniform.GetUniform(); double r = Math.Sqrt(-2.0 * Math.Log(u1)); double theta = 2.0 * Math.PI * u2; return(r * Math.Sin(theta)); }
public override double ComputeValue() { if (!double.IsNaN(this.Min)) { if (!double.IsNaN(this.Max)) { return(GenerateUniform.GetUniform(this.Min, this.Max)); } return(this.Min + GenerateUniform.GetUniform()); } return(GenerateUniform.GetUniform()); }
/// <summary> /// Get gamma random sample with parameters /// </summary> /// <param name="shape"></param> /// <param name="scale"></param> /// <returns></returns> public static double GetGamma(double shape, double scale) { // 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. double d, c, x, xsquared, v, u; if (shape >= 1.0) { d = shape - 1.0 / 3.0; c = 1.0 / Math.Sqrt(9.0 * d); for (; ;) { do { x = GenerateNormal.GetNormal(); v = 1.0 + c * x; }while (v <= 0.0); v = v * v * v; u = GenerateUniform.GetUniform(); xsquared = x * x; if (u < 1.0 - .0331 * xsquared * xsquared || Math.Log(u) < 0.5 * xsquared + d * (1.0 - v + Math.Log(v))) { return(scale * d * v); } } } else if (shape <= 0.0) { string msg = string.Format("Shape must be positive. Received {0}.", shape); throw new ArgumentOutOfRangeException(msg); } else { double g = GetGamma(shape + 1.0, 1.0); double w = GenerateUniform.GetUniform(); return(scale * g * Math.Pow(w, 1.0 / shape)); } }