private int inverseProbability()

in commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/AbstractDiscreteDistribution.java [148:201]


    private int inverseProbability(double p, double q, boolean complement) {

        int lower = getSupportLowerBound();
        if (p == 0) {
            return lower;
        }
        int upper = getSupportUpperBound();
        if (q == 0) {
            return upper;
        }

        // The binary search sets the upper value to the mid-point
        // based on fun(x) >= 0. The upper value is returned.
        //
        // Create a function to search for x where the upper bound can be
        // lowered if:
        // cdf(x) >= p
        // sf(x)  <= q
        final IntUnaryOperator fun = complement ?
            x -> Double.compare(q, survivalProbability(x)) :
            x -> Double.compare(cumulativeProbability(x), p);

        if (lower == Integer.MIN_VALUE) {
            if (fun.applyAsInt(lower) >= 0) {
                return lower;
            }
        } else {
            // this ensures:
            // cumulativeProbability(lower) < p
            // survivalProbability(lower) > q
            // which is important for the solving step
            lower -= 1;
        }

        // use the one-sided Chebyshev inequality to narrow the bracket
        // cf. AbstractContinuousDistribution.inverseCumulativeProbability(double)
        final double mu = getMean();
        final double sig = Math.sqrt(getVariance());
        final boolean chebyshevApplies = Double.isFinite(mu) &&
                                         ArgumentUtils.isFiniteStrictlyPositive(sig);

        if (chebyshevApplies) {
            double tmp = mu - sig * Math.sqrt(q / p);
            if (tmp > lower) {
                lower = ((int) Math.ceil(tmp)) - 1;
            }
            tmp = mu + sig * Math.sqrt(p / q);
            if (tmp < upper) {
                upper = ((int) Math.ceil(tmp)) - 1;
            }
        }

        return solveInverseProbability(fun, lower, upper);
    }