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

namespace StatisticalDistribution
{
    // F(x) = (x - A) / (B - A)
    // f(x) = 1 / (B - A)
    // x >= A   ;   x <= B

    public class UniformDist : Distribution
    {
        public static string abbr = "U";
        private double lowerBound;
        private double upperBound;
        private double range;
        

        #region CONSTRUCTORS
        public UniformDist(double lowerBound, double upperBound)
            : base(Type.Uniform)
        {
            this.lowerBound = lowerBound;
            this.upperBound = upperBound;
            this.range = this.upperBound - this.lowerBound;
        }
        #endregion

        #region OVERRIDE
        public override double pdf(double x) { return 1.0 / range; }
        public override double cdf(double x)
        {
            if (x < this.lowerBound) { return 0.0; }
            if (x > this.upperBound) { return 1.0; }
            return (x - this.lowerBound) / this.range;
        }
        public override double cdfInv(double p) { return this.range * p + this.lowerBound; }
        public override double variance() { return Math.Pow(this.range, 2.0) / 12.0; }
        public override double mean() { return (this.lowerBound + this.upperBound) / 2.0; }
        public override double std() { return this.range / Math.Sqrt(12.0); }
        public override double skewness() { return 0.0; }
        public override double kurtosis() { return Math.Pow(this.range, 4.0) / 80.0; }
        public override double mode() { throw new NotImplementedException(); }
        public override double median() { return this.mean(); }
        public override double Q1() { return (3.0 * this.lowerBound + this.upperBound) / 4.0; }
        public override double Q3() { return (this.lowerBound + 3.0 * this.upperBound) / 4.0; } 
        #endregion

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

    }
}
