﻿using System;
using UnityEngine;
using Random = UnityEngine.Random;

public static class Util
{
	public static float RandomNormal()
	{
		var u1 = Random.value;
		var u2 = Random.value;

		return Mathf.Sqrt(-2.0f * Mathf.Log(u1)) * Mathf.Sin(2.0f * Mathf.PI * u2);
	}

	public static float RandomExponential()
	{
		return -Mathf.Log(Random.value);
	}

	public static float RandomGamma(float shape, float scale)
	{
		float d, c, x, xsquared, v, u;

		if (shape >= 1.0) {
			d = shape - 1.0f / 3.0f;
			c = 1.0f / Mathf.Sqrt(9.0f * d);

			while (true) {
				do {
					x = RandomNormal();
					v = 1.0f + c * x;
				} while (v <= 0.0);
				v = v * v * v;
				u = Random.value;

				xsquared = x * x;
				if (u < 1.0f - 0.0331f * xsquared * xsquared || Mathf.Log(u) < 0.5f * xsquared + d * (1.0 - v + Mathf.Log(v))) {
					return scale * d * v;
				}
			}
		}

		if (shape <= 0.0f) {
			throw new ArgumentOutOfRangeException(string.Format("Shape must be positive. Received {0}.", shape));
		}

		var g = RandomGamma(shape + 1.0f, 1.0f);
		var w = Random.value;

		return scale * g * Mathf.Pow(w, 1.0f / shape);
	}

	public static float RandomChiSquared(float df)
	{
		return RandomGamma(0.5f * df, 2.0f);
	}
}