Exemplo n.º 1
0
        /// <summary>
        /// Computes the inverse of the cumulative distribution function (InvCDF) for the distribution
        /// at the given probability. This is also known as the quantile or percent point function.
        /// </summary>
        /// <param name="p">The location at which to compute the inverse cumulative density.</param>
        /// <param name="location">The location (μ) of the distribution.</param>
        /// <param name="scale">The scale (σ) of the distribution. Range: σ > 0.</param>
        /// <param name="freedom">The degrees of freedom (ν) for the distribution. Range: ν > 0.</param>
        /// <returns>the inverse cumulative density at <paramref name="p"/>.</returns>
        /// <seealso cref="InverseCumulativeDistribution"/>
        /// <remarks>WARNING: currently not an explicit implementation, hence slow and unreliable.</remarks>
        public static double InvCDF(double location, double scale, double freedom, double p)
        {
            if (scale <= 0.0 || freedom <= 0.0)
            {
                throw new ArgumentException(Resources.InvalidDistributionParameters);
            }

            // TODO JVG we can probably do a better job for Cauchy special case
            if (double.IsPositiveInfinity(freedom))
            {
                return(Normal.InvCDF(location, scale, p));
            }

            if (p == 0.5d)
            {
                return(location);
            }

            // TODO PERF: We must implement this explicitly instead of solving for CDF^-1
            return(Brent.FindRoot(x =>
            {
                var k = (x - location) / scale;
                var h = freedom / (freedom + (k * k));
                var ib = 0.5 * SpecialFunctions.BetaRegularized(freedom / 2.0, 0.5, h);
                return x <= location ? ib - p : 1.0 - ib - p;
            }, -800, 800, accuracy: 1e-12));
        }