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 GammaDist : Distribution
    {

        public static string abbr = "Gam";
        private double shape;
        private double scale;
        private double alphaLnTheta;
        private double lngammaAlpha;

        #region CONSTRUCTORS
        public GammaDist(double shape, double scale)
            : base(Type.Gamma)
        {
            this.shape = shape;
            this.scale = scale;
            this.alphaLnTheta = shape * Math.Log(scale);
            this.lngammaAlpha = Functions.GammaLn(shape);
        } 
        #endregion

        #region OVERRIDE
        public override double pdf(double x)
        {
            return Math.Exp(
                    ((shape - 1.0) * Math.Log(x))
                    - (x / scale)
                    - lngammaAlpha
                    - alphaLnTheta
                    );
        }
        public override double cdf(double x) { return Functions.GammaRegularized(shape, x / scale); }
        public override double cdfInv(double p) { return Functions.GammaRegularizedInverse(shape, p) * scale; }
        public override double variance() { return shape * Math.Pow(scale, 2.0); }
        public override double mean() { return shape * scale; }
        public override double std() { return Math.Sqrt(shape) * scale; }
        public override double skewness() { return 2.0 / Math.Sqrt(shape); }
        public override double kurtosis() { return 6.0 / shape; }
        public override double mode()
        {
            if (shape < 1) { throw new NotImplementedException(); }
            return (shape - 1.0) * scale;
        }
        public override double median() { throw new NotImplementedException(); }
        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>() { shape, scale }, DStr.PAR, DStr.DEL); }
        public override Distribution Clone() { return new GammaDist(shape, scale); } 
        #endregion

    }
}
