A small RTS game im making in unity3D
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

#### 234 lines 8.4 KiB Raw Permalink Blame History

 `using System;` ``` ``` `namespace TestSimpleRNG` `{` ` /// ` ` /// SimpleRNG is a simple random number generator based on ` ` /// George Marsaglia's MWC (multiply with carry) generator.` ` /// Although it is very simple, it passes Marsaglia's DIEHARD` ` /// series of random number generator tests.` ` /// ` ` /// Written by John D. Cook ` ` /// http://www.johndcook.com` ` /// ` ` public class SimpleRNG` ` {` ` private static uint m_w;` ` private static uint m_z;` ``` ``` ` static SimpleRNG()` ` {` ` // These values are not magical, just the default values Marsaglia used.` ` // Any pair of unsigned integers should be fine.` ` m_w = 521288629;` ` m_z = 362436069;` ` }` ``` ``` ` // The random generator seed can be set three ways:` ` // 1) specifying two non-zero unsigned integers` ` // 2) specifying one non-zero unsigned integer and taking a default value for the second` ` // 3) setting the seed from the system time` ` public static void SetSeed(uint u, uint v)` ` {` ` if (u != 0) m_w = u; ` ` if (v != 0) m_z = v;` ` }` ``` ``` ` public static void SetSeed(uint u)` ` {` ` m_w = u;` ` }` ``` ``` ` public static void SetSeedFromSystemTime()` ` {` ` System.DateTime dt = System.DateTime.Now;` ` long x = dt.ToFileTime();` ` SetSeed((uint)(x >> 16), (uint)(x % 4294967296));` ` }` ``` ``` ` // Produce a uniform random sample from the open interval (0, 1).` ` // The method will not return either end point.` ` public static double GetUniform()` ` {` ` // 0 <= u < 2^32` ` uint u = GetUint();` ` // The magic number below is 1/(2^32 + 2).` ` // The result is strictly between 0 and 1.` ` return (u + 1.0) * 2.328306435454494e-10;` ` }` ``` ``` ` // This is the heart of the generator.` ` // It uses George Marsaglia's MWC algorithm to produce an unsigned integer.` ` // See http://www.bobwheeler.com/statistics/Password/MarsagliaPost.txt` ` private static uint GetUint()` ` {` ` m_z = 36969 * (m_z & 65535) + (m_z >> 16);` ` m_w = 18000 * (m_w & 65535) + (m_w >> 16);` ` return (m_z << 16) + m_w;` ` }` ` ` ` // Get normal (Gaussian) random sample with mean 0 and standard deviation 1` ` public static double GetNormal()` ` {` ` // Use Box-Muller algorithm` ` double u1 = GetUniform();` ` double u2 = GetUniform();` ` double r = Math.Sqrt( -2.0*Math.Log(u1) );` ` double theta = 2.0*Math.PI*u2;` ` return r*Math.Sin(theta);` ` }` ` ` ` // Get normal (Gaussian) random sample with specified mean and standard deviation` ` public static double GetNormal(double mean, double standardDeviation)` ` {` ` if (standardDeviation <= 0.0)` ` {` ` string msg = string.Format("Shape must be positive. Received {0}.", standardDeviation);` ` throw new ArgumentOutOfRangeException(msg);` ` }` ` return mean + standardDeviation*GetNormal();` ` }` ` ` ` // Get exponential random sample with mean 1` ` public static double GetExponential()` ` {` ` return -Math.Log( GetUniform() );` ` }` ``` ``` ` // Get exponential random sample with specified mean` ` public static double GetExponential(double mean)` ` {` ` if (mean <= 0.0)` ` {` ` string msg = string.Format("Mean must be positive. Received {0}.", mean);` ` throw new ArgumentOutOfRangeException(msg);` ` }` ` return mean*GetExponential();` ` }` ``` ``` ` 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 = GetNormal();` ` v = 1.0 + c*x;` ` }` ` while (v <= 0.0);` ` v = v*v*v;` ` u = 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 = GetUniform();` ` return scale*g*Math.Pow(w, 1.0/shape);` ` }` ` }` ``` ``` ` public static double GetChiSquare(double degreesOfFreedom)` ` {` ` // A chi squared distribution with n degrees of freedom` ` // is a gamma distribution with shape n/2 and scale 2.` ` return GetGamma(0.5 * degreesOfFreedom, 2.0);` ` }` ``` ``` ` public static double GetInverseGamma(double shape, double scale)` ` {` ` // If X is gamma(shape, scale) then` ` // 1/Y is inverse gamma(shape, 1/scale)` ` return 1.0 / GetGamma(shape, 1.0 / scale);` ` }` ``` ``` ` public static double GetWeibull(double shape, double scale)` ` {` ` if (shape <= 0.0 || scale <= 0.0)` ` {` ` string msg = string.Format("Shape and scale parameters must be positive. Recieved shape {0} and scale{1}.", shape, scale);` ` throw new ArgumentOutOfRangeException(msg);` ` }` ` return scale * Math.Pow(-Math.Log(GetUniform()), 1.0 / shape);` ` }` ``` ``` ` public static double GetCauchy(double median, double scale)` ` {` ` if (scale <= 0)` ` {` ` string msg = string.Format("Scale must be positive. Received {0}.", scale);` ` throw new ArgumentException(msg);` ` }` ``` ``` ` double p = GetUniform();` ``` ``` ` // Apply inverse of the Cauchy distribution function to a uniform` ` return median + scale*Math.Tan(Math.PI*(p - 0.5));` ` }` ``` ``` ` public static double GetStudentT(double degreesOfFreedom)` ` {` ` if (degreesOfFreedom <= 0)` ` {` ` string msg = string.Format("Degrees of freedom must be positive. Received {0}.", degreesOfFreedom);` ` throw new ArgumentException(msg);` ` }` ``` ``` ` // See Seminumerical Algorithms by Knuth` ` double y1 = GetNormal();` ` double y2 = GetChiSquare(degreesOfFreedom);` ` return y1 / Math.Sqrt(y2 / degreesOfFreedom);` ` }` ``` ``` ` // The Laplace distribution is also known as the double exponential distribution.` ` public static double GetLaplace(double mean, double scale)` ` {` ` double u = GetUniform();` ` return (u < 0.5) ?` ` mean + scale*Math.Log(2.0*u) :` ` mean - scale*Math.Log(2*(1-u));` ` }` ``` ``` ` public static double GetLogNormal(double mu, double sigma)` ` {` ` return Math.Exp(GetNormal(mu, sigma));` ` }` ``` ``` ` public static double GetBeta(double a, double b)` ` {` ` if (a <= 0.0 || b <= 0.0)` ` {` ` string msg = string.Format("Beta parameters must be positive. Received {0} and {1}.", a, b);` ` throw new ArgumentOutOfRangeException(msg);` ` }` ``` ``` ` // There are more efficient methods for generating beta samples.` ` // However such methods are a little more efficient and much more complicated.` ` // For an explanation of why the following method works, see` ` // http://www.johndcook.com/distribution_chart.html#gamma_beta` ` double u = GetGamma(a, 1.0);` ` double v = GetGamma(b, 1.0);` ` return u / (u + v);` ` }` ` }` ```} ``` ``` ```