org.renjin.Distributions.java Source code

Java tutorial

Introduction

Here is the source code for org.renjin.Distributions.java

Source

/*
 * R : A Computer Language for Statistical Data Analysis
 * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
 * Copyright (C) 1997--2008  The R Development Core Team
 * Copyright (C) 2003, 2004  The R Foundation
 * Copyright (C) 2010 bedatadriven
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.renjin;

import org.apache.commons.math.MathException;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.distribution.AbstractContinuousDistribution;
import org.apache.commons.math.distribution.BetaDistributionImpl;
import org.apache.commons.math.distribution.BinomialDistributionImpl;
import org.apache.commons.math.distribution.CauchyDistributionImpl;
import org.apache.commons.math.distribution.ChiSquaredDistributionImpl;
import org.apache.commons.math.distribution.ContinuousDistribution;
import org.apache.commons.math.distribution.Distribution;
import org.apache.commons.math.distribution.ExponentialDistributionImpl;
import org.apache.commons.math.distribution.FDistributionImpl;
import org.apache.commons.math.distribution.GammaDistributionImpl;
import org.apache.commons.math.distribution.HypergeometricDistributionImpl;
import org.apache.commons.math.distribution.IntegerDistribution;
import org.apache.commons.math.distribution.NormalDistributionImpl;
import org.apache.commons.math.distribution.PascalDistributionImpl;
import org.apache.commons.math.distribution.PoissonDistributionImpl;
import org.apache.commons.math.distribution.TDistributionImpl;
import org.apache.commons.math.distribution.WeibullDistributionImpl;
import org.renjin.stats.internals.distributions.Beta;
import org.renjin.stats.internals.distributions.Binom;
import org.renjin.stats.internals.distributions.ChiSquare;
import org.renjin.stats.internals.distributions.ChisquareZeroDfDistribution;
import org.renjin.stats.internals.distributions.F;
import org.renjin.stats.internals.distributions.Geometric;
import org.renjin.stats.internals.distributions.LNorm;
import org.renjin.stats.internals.distributions.LogisticDistribution;
import org.renjin.stats.internals.distributions.SignRank;
import org.renjin.stats.internals.distributions.StudentsT;
import org.renjin.stats.internals.distributions.Tukey;
import org.renjin.stats.internals.distributions.UniformDistribution;
import org.renjin.stats.internals.distributions.Wilcox;

/**
 * Density, mass, cumulative and inverse cumulative distribution functions.
 *
 * <p>The methods defined here serve as an adapter between the R function conventions and the
 * Apache Commons Math Library. (See {@link Distribution}
 */
public class Distributions {

    private Distributions() {
    }

    // TODO: there are several distributions for which the inverse is not provided
    // by commons math, and most non-central distributions are not present.
    // these should be implemented in the distributions package but using the Commons Math API
    /**
     * Calculates the value of the density function at {@code x}
     * for the given continuous distribution
     *
     * @param dist the distribution of the random variable
     * @param x the value
     * @param log whether to return the natural logarithm of the function's value
     * @return the (natural logarithm) of the relative likelihood for the random
     * variable to take the value {@code x}
     */
    private static double d(AbstractContinuousDistribution dist, double x, boolean log) {
        double d = dist.density(x);
        if (log) {
            d = Math.log(d);
        }
        return d;
    }

    /**
     * Calculates the value of the probability mass function at {@code x}
     * for the given discrete distribution
     *
     * @param dist the discrete distribution
     * @param x the value
     * @param log whether to return the natural logarithm of the probability
     * @return  the (natural logarithm) of the probability for the  random variable
     *  to take the value {@code x}
     */
    private static double d(IntegerDistribution dist, double x, boolean log) {
        double d = dist.probability(x);
        if (log) {
            d = Math.log(d);
        }
        return d;
    }

    /**
     *
     * Calculates the value of the cumulative distribution function
     *
     * @param dist the distribution
     * @param q the value
     * @param lowerTail if true, return the value P(x < q), otherwise P(x > q)
     * @param logP  if true, return the natural logarithm of the probability
     * @return  the probability that the random variable will take the value less than (greater than)
     * {@code q}
     */
    private static double p(Distribution dist, double q, boolean lowerTail, boolean logP) {
        double p;
        try {
            p = dist.cumulativeProbability(q);
        } catch (MathException e) {
            return Double.NaN;
        } catch (MathRuntimeException e) {
            return Double.NaN;
        }
        if (!lowerTail) {
            p = 1.0 - p;
        }
        if (logP) {
            p = Math.log(p);
        }

        return p;
    }

    /**
     * Calculates the value of the inverse cumulative probability function according to standard R arguments.
     *
     * @param dist the continuous distribution
     * @param p the probability
     * @param lowerTail
     * @param logP if true, interpret {@code p} as the natural logarithm of the probability
     * @return the value fo
     */
    private static double q(ContinuousDistribution dist, double p, boolean lowerTail, boolean logP) {
        if (logP) {
            p = Math.exp(p);
        }
        double q = 0;
        try {
            q = dist.inverseCumulativeProbability(p);
        } catch (IllegalArgumentException e) {
            return Double.NaN;
        } catch (MathException e) {
            return Double.NaN;
        } catch (MathRuntimeException e) {
            return Double.NaN;
        }
        if (!lowerTail) {
            q = -q;
        }
        return q;
    }

    private static double q(IntegerDistribution dist, double p, boolean lowerTail, boolean logP) {
        if (logP) {
            p = Math.exp(p);
        }
        double q = 0;
        try {
            q = dist.inverseCumulativeProbability(p);
        } catch (IllegalArgumentException e) {
            return Double.NaN;
        } catch (MathException e) {
            return Double.NaN;
        } catch (MathRuntimeException e) {
            return Double.NaN;
        }
        if (!lowerTail) {
            q = -q;
        }
        return q;
    }

    //@Internal
    public static double dnorm(final double x, final double mean, final double sd, boolean log) {
        return d(new NormalDistributionImpl(mean, sd), x, log);
    }

    //@Internal
    public static double pnorm(final double q, final double mean, final double sd, boolean lowerTail,
            boolean logP) {
        return p(new NormalDistributionImpl(mean, sd), q, lowerTail, logP);
    }

    //@Internal
    public static double plnorm(final double q, final double logmean, final double logsd, boolean lowerTail,
            boolean logP) {
        return p(new NormalDistributionImpl(logmean, logsd), Math.log(q), lowerTail, logP);
    }

    //@Internal
    public static double qnorm(final double p, final double mean, final double sd, boolean lowerTail,
            boolean logP) {
        return q(new NormalDistributionImpl(mean, sd), p, lowerTail, logP);
    }

    //@Internal
    public static double qlnorm(final double p, final double meanlog, final double sdlog, boolean lowerTail,
            boolean logP) {
        return Math.exp(q(new NormalDistributionImpl(meanlog, sdlog), p, lowerTail, logP));
    }

    //@Internal
    public static double dlnorm(final double x, final double meanlog, final double sdlog, boolean logP) {
        return LNorm.dlnorm(x, meanlog, sdlog, logP);
    }

    //@Internal
    public static double dbeta(final double x, final double shape1, final double shape2, boolean log) {
        return d(new BetaDistributionImpl(shape1, shape2), x, log);
    }

    //@Internal
    public static double dnbeta(final double x, final double shape1, final double shape2, final double ncp,
            boolean log) {
        return Beta.dnbeta(x, shape1, shape2, ncp, log);
    }

    //@Internal
    public static double pbeta(final double q, final double shape1, final double shape2, boolean lowerTail,
            boolean logP) {
        return p(new BetaDistributionImpl(shape1, shape2), q, lowerTail, logP);
    }

    //@Internal
    public static double pnbeta(final double q, final double shape1, final double shape2, final double ncp,
            boolean lowerTail, boolean logP) {
        return Beta.pnbeta(q, shape1, shape2, ncp, lowerTail, logP);
    }

    //@Internal
    public static double qbeta(final double p, final double shape1, final double shape2, boolean lowerTail,
            boolean logP) {
        return q(new BetaDistributionImpl(shape1, shape2), p, lowerTail, logP);
    }

    //@Internal
    public static double qnbeta(final double p, final double shape1, final double shape2, final double ncp,
            boolean lowerTail, boolean logP) {
        return Beta.qnbeta(p, shape1, shape2, ncp, lowerTail, logP);
    }

    //@Internal
    public static double dchisq(final double x, final double df, boolean log) {
        return d(new ChiSquaredDistributionImpl(df), x, log);
    }

    //@Internal
    public static double dnchisq(final double x, final double df, final double ncp, boolean log) {
        return ChiSquare.dnchisq(x, df, ncp, log);
    }

    //@Internal
    public static double pchisq(final double q, final double df, boolean lowerTail, boolean logP) {
        if (df == 0) {
            return p(new ChisquareZeroDfDistribution(), q, lowerTail, logP);
        } else {
            return p(new ChiSquaredDistributionImpl(df), q, lowerTail, logP);
        }
    }

    //@Internal
    public static double pnchisq(final double q, final double df, final double ncp, boolean lowerTail,
            boolean logP) {
        return ChiSquare.pnchisq(q, df, ncp, lowerTail, logP);
    }

    //@Internal
    public static double qchisq(final double p, final double df, boolean lowerTail, boolean logP) {
        if (df == 0) {
            return q(new ChisquareZeroDfDistribution(), p, lowerTail, logP);
        } else {
            return q(new ChiSquaredDistributionImpl(df), p, lowerTail, logP);
        }
    }

    //@Internal
    public static double qnchisq(final double p, final double df, final double ncp, boolean lowerTail,
            boolean logP) {
        return ChiSquare.qnchisq(p, df, ncp, lowerTail, logP);
    }

    //@Internal
    public static double dexp(final double x, final double rate, boolean log) {
        return d(new ExponentialDistributionImpl(1.0 / rate), x, log);
    }

    //@Internal
    public static double pexp(final double q, final double rate, boolean lowerTail, boolean logP) {
        return p(new ExponentialDistributionImpl(1.0 / rate), q, lowerTail, logP);
    }

    //@Internal
    public static double qexp(final double p, final double rate, boolean lowerTail, boolean logP) {
        return q(new ExponentialDistributionImpl(1.0 / rate), p, lowerTail, logP);
    }

    //@Internal
    public static double dt(final double x, final double df, boolean log) {
        return d(new TDistributionImpl(df), x, log);
    }

    //@Internal
    public static double dnt(final double x, final double df, final double ncp, boolean log) {
        return StudentsT.dnt(x, df, ncp, log);
    }

    //@Internal
    public static double pt(final double q, final double df, boolean lowerTail, boolean logP) {
        return p(new TDistributionImpl(df), q, lowerTail, logP);
    }

    //@Internal
    public static double pnt(final double q, final double df, final double ncp, boolean lowerTail, boolean logP) {
        return StudentsT.pnt(q, df, ncp, lowerTail, logP);
    }

    //@Internal
    public static double qt(final double p, final double df, boolean lowerTail, boolean logP) {
        return q(new TDistributionImpl(df), p, lowerTail, logP);
    }

    //@Internal
    public static double qnt(final double p, final double df, final double ncp, boolean lowerTail, boolean logP) {
        return StudentsT.qnt(p, df, ncp, lowerTail, logP);
    }

    //@Internal
    public static double dpois(final double x, final double lambda, boolean log) {
        return d(new PoissonDistributionImpl(lambda), x, log);
    }

    //@Internal
    public static double ppois(final double q, final double lambda, boolean lowerTail, boolean logP) {
        return p(new PoissonDistributionImpl(lambda), q, lowerTail, logP);
    }

    public static double qpois(double p, double lambda, boolean lowerTail, boolean logP) {
        return q(new PoissonDistributionImpl(lambda), p, lowerTail, logP);
    }

    //@Internal
    public static double dbinom(final double x, final int size, final double prob, boolean log) {
        return d(new BinomialDistributionImpl(size, prob), x, log);
    }

    //@Internal
    public static double dnbinom(final double x, final int size, final double prob, boolean log) {
        return d(new PascalDistributionImpl(size, prob), x, log);
    }

    //@Internal
    public static double dnbinom_mu(final double x, final int size, final double mu, boolean log) {
        return Binom.dnbinom_mu(x, size, mu, log);
    }

    //@Internal
    public static double pbinom(final double x, final int size, final double prob, boolean lowerTail,
            boolean logP) {
        return p(new BinomialDistributionImpl(size, prob), x, lowerTail, logP);
    }

    //@Internal
    public static double pnbinom(final double x, final int size, final double prob, boolean lowerTail,
            boolean logP) {
        return p(new PascalDistributionImpl(size, prob), x, lowerTail, logP);
    }

    //@Internal
    public static double pnbinom_mu(final double x, final int size, final double mu, boolean lowerTail,
            boolean logP) {
        if (!logP) {
            return Binom.pnbinom_mu(x, size, mu, lowerTail ? false : true, logP);
        } else {
            return Binom.pnbinom_mu(x, size, mu, lowerTail, logP);
        }
    }

    //@Internal
    public static double qbinom(final double p, final int size, final double prob, boolean lowerTail,
            boolean logP) {
        return q(new BinomialDistributionImpl(size, prob), p, lowerTail, logP) + 1;
    }

    //@Internal
    public static double qnbinom(final double p, final double size, final double prob, boolean lower_tail,
            boolean log_p) {
        return Binom.qnbinom(p, size, prob, lower_tail, log_p);
    }

    //@Internal
    public static double qnbinom_mu(final double p, final double size, final double mu, boolean lower_tail,
            boolean log_p) {
        return Binom.qnbinom_mu(p, size, mu, lower_tail, log_p);
    }

    //@Internal
    public static double dcauchy(final double x, final double location, final double scale, boolean log) {
        return d(new CauchyDistributionImpl(location, scale), x, log);
    }

    //@Internal
    public static double pcauchy(final double q, final double location, final double scale, boolean lowerTail,
            boolean logP) {
        return p(new CauchyDistributionImpl(location, scale), q, lowerTail, logP);
    }

    //@Internal
    public static double qcauchy(final double p, final double location, final double scale, boolean lowerTail,
            boolean logP) {
        return q(new CauchyDistributionImpl(location, scale), p, lowerTail, logP);
    }

    //@Internal
    public static double df(final double x, final double df1, final double df2, boolean log) {
        return d(new FDistributionImpl(df1, df2), x, log);
    }

    //@Internal
    public static double dnf(final double x, final double df1, final double df2, final double ncp, boolean log) {
        return F.dnf(x, df1, df2, ncp, log);
    }

    //@Internal
    public static double pf(final double q, final double df1, final double df2, boolean lowerTail, boolean logP) {
        return p(new FDistributionImpl(df1, df2), q, lowerTail, logP);
    }

    //@Internal
    public static double pnf(final double q, final double df1, final double df2, final double ncp,
            boolean lowerTail, boolean logP) {
        return F.pnf(q, df1, df2, ncp, lowerTail, logP);
    }

    //@Internal
    public static double qf(final double p, final double df1, final double df2, boolean lowerTail, boolean logP) {
        return q(new FDistributionImpl(df1, df2), p, lowerTail, logP);
    }

    //@Internal
    public static double qnf(final double p, final double df1, final double df2, final double ncp,
            boolean lowerTail, boolean logP) {
        return F.qnf(p, df1, df2, ncp, lowerTail, logP);
    }

    //@Internal
    public static double dgamma(final double x, final double shape, final double scale, boolean log) {
        return d(new GammaDistributionImpl(shape, scale), x, log);
    }

    //@Internal
    public static double pgamma(final double q, final double shape, final double scale, boolean lowerTail,
            boolean logP) {
        return p(new GammaDistributionImpl(shape, scale), q, lowerTail, logP);
    }

    //@Internal
    public static double qgamma(final double p, final double shape, final double scale, boolean lowerTail,
            boolean logP) {
        return q(new GammaDistributionImpl(shape, scale), p, lowerTail, logP);
    }

    //@Internal
    public static double dunif(final double x, final double min, final double max, boolean log) {
        double d = new UniformDistribution(min, max).density(x);
        if (log) {
            d = Math.log(d);
        }
        return d;
    }

    //@Internal
    public static double punif(final double q, final double min, final double max, boolean lowerTail,
            boolean logP) {
        return p(new UniformDistribution(min, max), q, lowerTail, logP);
    }

    //@Internal
    public static double qunif(final double p, final double min, final double max, boolean lowerTail,
            boolean logP) {
        return q(new UniformDistribution(min, max), p, lowerTail, logP);
    }

    //@Internal
    public static double dweibull(final double x, final double shape, final double scale, boolean log) {
        return d(new WeibullDistributionImpl(shape, scale), x, log);
    }

    //@Internal
    public static double pweibull(final double q, final double shape, final double scale, boolean lowerTail,
            boolean logP) {
        return p(new WeibullDistributionImpl(shape, scale), q, lowerTail, logP);
    }

    //@Internal
    public static double qweibull(final double p, final double shape, final double scale, boolean lowerTail,
            boolean logP) {
        return q(new WeibullDistributionImpl(shape, scale), p, lowerTail, logP);
    }

    //@Internal
    public static double dhyper(final double x, final double whiteBalls, final double blackBalls,
            final double sampleSize, boolean log) {
        return d(new HypergeometricDistributionImpl((int) (whiteBalls + blackBalls), (int) whiteBalls,
                (int) sampleSize), x, log);
    }

    //@Internal
    public static double phyper(final double q, final double x, final double whiteBalls, final double blackBalls,
            final double sampleSize, boolean lowerTail, boolean logP) {
        return p(new HypergeometricDistributionImpl((int) (whiteBalls + blackBalls), (int) whiteBalls,
                (int) sampleSize), q, lowerTail, logP);
    }

    public static double qhyper(double p, double m, double n, double k, boolean lowerTail, boolean logP) {
        return q(new HypergeometricDistributionImpl((int) m, (int) n, (int) k), p, lowerTail, logP);
    }

    /*
    public static double dgeom(final int x, final double p, final boolean log) {
    if (log) {
    return (Math.log(p * Math.pow(1 - p, x)));
    } else {
    return (p * Math.pow(1 - p, x));
    }
    }
     */
    //@Internal
    public static double pgeom(final double q, final double prob, boolean lowerTail, boolean log) {
        return (Geometric.pgeom(q, prob, lowerTail, log));
    }

    //@Internal
    public static double dgeom(final double x, final double prob, boolean log) {
        return Geometric.dgeom(x, prob, log);
    }

    //@Internal
    public static double qgeom(final double p, final double prob, boolean lowerTail, boolean log) {
        return Geometric.qgeom(p, prob, lowerTail, log);
    }

    //@Internal
    public static double plogis(final double p, final double m, final double s, boolean lowerTail, boolean logP) {
        return p(new LogisticDistribution(m, s), p, lowerTail, logP);
    }

    //@Internal
    public static double dlogis(final double x, final double location, final double scale, boolean log) {
        return d(new LogisticDistribution(location, scale), x, log);
    }

    //@Internal
    public static double qlogis(final double p, final double m, final double s, boolean lowerTail, boolean logP) {
        return q(new LogisticDistribution(m, s), p, lowerTail, logP);
    }

    //@Internal
    public static double qsignrank(double p, double n, boolean lowerTail, boolean logP) {
        return SignRank.qsignrank(p, n, lowerTail, logP);
    }

    //@Internal
    public static double psignrank(double p, double n, boolean lowerTail, boolean logP) {
        return SignRank.psignrank(p, n, lowerTail, logP);
    }

    //@Internal
    public static double dsignrank(double x, double n, boolean logP) {
        return SignRank.dsignrank(x, n, logP);
    }

    //@Internal
    public static double dwilcox(double x, double m, double n, boolean logP) {
        return Wilcox.dwilcox(x, m, n, logP);
    }

    //@Internal
    public static double pwilcox(double q, double m, double n, boolean lowerTail, boolean logP) {
        return Wilcox.pwilcox(q, m, n, lowerTail, logP);
    }

    //@Internal
    public static double qwilcox(double p, double m, double n, boolean lowerTail, boolean logP) {
        return Wilcox.qwilcox(p, m, n, lowerTail, logP);
    }

    //@Internal
    public static double ptukey(final double q, final double nranges, final double nmeans, final double df,
            boolean lowerTail, boolean logP) {
        return (Tukey.ptukey(q, nranges, nmeans, df, lowerTail, logP));
    }

    //@Internal
    public static double qtukey(final double p, final double nranges, final double nmeans, final double df,
            boolean lowerTail, boolean logP) {
        return (Tukey.qtukey(p, nranges, nmeans, df, lowerTail, logP));
    }
}