001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.statistics.distribution;
018
019import org.apache.commons.rng.UniformRandomProvider;
020
021/**
022 * Implementation of the <a href="http://en.wikipedia.org/wiki/Chi-squared_distribution">chi-squared distribution</a>.
023 */
024public class ChiSquaredDistribution extends AbstractContinuousDistribution {
025    /** Internal Gamma distribution. */
026    private final GammaDistribution gamma;
027
028    /**
029     * Creates a distribution.
030     *
031     * @param degreesOfFreedom Degrees of freedom.
032     */
033    public ChiSquaredDistribution(double degreesOfFreedom) {
034        gamma = new GammaDistribution(degreesOfFreedom / 2, 2);
035    }
036
037    /**
038     * Access the number of degrees of freedom.
039     *
040     * @return the degrees of freedom.
041     */
042    public double getDegreesOfFreedom() {
043        return gamma.getShape() * 2;
044    }
045
046    /** {@inheritDoc} */
047    @Override
048    public double density(double x) {
049        return gamma.density(x);
050    }
051
052    /** {@inheritDoc} **/
053    @Override
054    public double logDensity(double x) {
055        return gamma.logDensity(x);
056    }
057
058    /** {@inheritDoc} */
059    @Override
060    public double cumulativeProbability(double x)  {
061        return gamma.cumulativeProbability(x);
062    }
063
064    /**
065     * {@inheritDoc}
066     *
067     * For {@code k} degrees of freedom, the mean is {@code k}.
068     */
069    @Override
070    public double getMean() {
071        return getDegreesOfFreedom();
072    }
073
074    /**
075     * {@inheritDoc}
076     *
077     * @return {@code 2 * k}, where {@code k} is the number of degrees of freedom.
078     */
079    @Override
080    public double getVariance() {
081        return 2 * getDegreesOfFreedom();
082    }
083
084    /**
085     * {@inheritDoc}
086     *
087     * The lower bound of the support is always 0 no matter the
088     * degrees of freedom.
089     *
090     * @return zero.
091     */
092    @Override
093    public double getSupportLowerBound() {
094        return 0;
095    }
096
097    /**
098     * {@inheritDoc}
099     *
100     * The upper bound of the support is always positive infinity no matter the
101     * degrees of freedom.
102     *
103     * @return {@code Double.POSITIVE_INFINITY}.
104     */
105    @Override
106    public double getSupportUpperBound() {
107        return Double.POSITIVE_INFINITY;
108    }
109
110    /**
111     * {@inheritDoc}
112     *
113     * The support of this distribution is connected.
114     *
115     * @return {@code true}
116     */
117    @Override
118    public boolean isSupportConnected() {
119        return true;
120    }
121
122    /**
123     * {@inheritDoc}
124     *
125     * <p>
126     * Sampling algorithms:
127     * <ul>
128     *  <li>
129     *   For {@code 0 < degreesOfFreedom < 2}:
130     *   <blockquote>
131     *    Ahrens, J. H. and Dieter, U.,
132     *    <i>Computer methods for sampling from gamma, beta, Poisson and binomial distributions,</i>
133     *    Computing, 12, 223-246, 1974.
134     *   </blockquote>
135     *  </li>
136     *  <li>
137     *  For {@code degreesOfFreedom >= 2}:
138     *   <blockquote>
139     *   Marsaglia and Tsang, <i>A Simple Method for Generating
140     *   Gamma Variables.</i> ACM Transactions on Mathematical Software,
141     *   Volume 26 Issue 3, September, 2000.
142     *   </blockquote>
143     *  </li>
144     * </ul>
145     */
146    @Override
147    public ContinuousDistribution.Sampler createSampler(final UniformRandomProvider rng) {
148        return gamma.createSampler(rng);
149    }
150}