using StatisticalDistribution.SpecialFunctions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using U.StringOperations;

namespace StatisticalDistribution
{
    public class NormalDist : Distribution
    {
        private double mu;
        private double sigma;

        public static string abbr = "N";
        private double sigmaSqrt2;
        private double oneOverSigmaSqrt2;

        #region CONSTRUCTORS
        public NormalDist(double mu, double sigma)
            : base(Distribution.Type.Normal)
        {
            this.mu = mu;
            this.sigma = sigma;
            this.sigmaSqrt2 = sigma * Math.Sqrt(2.0);
            this.oneOverSigmaSqrt2 = 1 / sigmaSqrt2;
        } 
        #endregion

        #region OVERRIDE
        public override double pdf(double x)
        {
            double xmu = x - mu;
            return Constants.InvSqrt2Pi / sigma * Math.Exp(xmu * xmu / (-2.0 * sigma * sigma));
        }
        public override double cdf(double x)
        {
            return 0.5 * (1.0 + Functions.Erf1((x - mu) / (sigma * Constants.Sqrt2)));
            //return 0.5 * (1.0 + Erf.calc((x - mu) * oneOverSigmaSqrt2));
        }
        public override double cdfInv(double p)
        {
            return (sigma * Constants.Sqrt2 * Functions.Erf1Inverse((2.0 * p) - 1.0)) + mu;
            //return mu + sigmaSqrt2 * Erf.calcInverse((2.0 * p) - 1.0);
        }
        public override double variance() { return Math.Pow(sigma, 2.0); }
        public override double mean() { return mu; }
        public override double std() { return sigma; }
        public override double skewness() { return 0.0; }
        public override double kurtosis() { return 3.0 * Math.Pow(sigma, 4.0); }
        public override double mode() { return mu; }
        public override double median() { return mu; }
        public override double Q1() { throw new NotImplementedException(); }
        public override double Q3() { throw new NotImplementedException(); } 
        #endregion

        #region TOSTRING and CLONE
        public override string ToString()
        {
            return StrFunc.getFuncString(abbr, new List<double>() { mu, sigma }, DStr.PAR, DStr.DEL);
        }
        public override Distribution Clone() { return new NormalDist(this.mu, this.sigma); } 
        #endregion

    }
}
