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 */ 017 package org.apache.commons.math3.distribution; 018 019 import org.apache.commons.math3.random.RandomGenerator; 020 import org.apache.commons.math3.random.Well19937c; 021 022 /** 023 * Implementation of the chi-squared distribution. 024 * 025 * @see <a href="http://en.wikipedia.org/wiki/Chi-squared_distribution">Chi-squared distribution (Wikipedia)</a> 026 * @see <a href="http://mathworld.wolfram.com/Chi-SquaredDistribution.html">Chi-squared Distribution (MathWorld)</a> 027 * @version $Id: ChiSquaredDistribution.java 1416643 2012-12-03 19:37:14Z tn $ 028 */ 029 public class ChiSquaredDistribution extends AbstractRealDistribution { 030 /** 031 * Default inverse cumulative probability accuracy 032 * @since 2.1 033 */ 034 public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9; 035 /** Serializable version identifier */ 036 private static final long serialVersionUID = -8352658048349159782L; 037 /** Internal Gamma distribution. */ 038 private final GammaDistribution gamma; 039 /** Inverse cumulative probability accuracy */ 040 private final double solverAbsoluteAccuracy; 041 042 /** 043 * Create a Chi-Squared distribution with the given degrees of freedom. 044 * 045 * @param degreesOfFreedom Degrees of freedom. 046 */ 047 public ChiSquaredDistribution(double degreesOfFreedom) { 048 this(degreesOfFreedom, DEFAULT_INVERSE_ABSOLUTE_ACCURACY); 049 } 050 051 /** 052 * Create a Chi-Squared distribution with the given degrees of freedom and 053 * inverse cumulative probability accuracy. 054 * 055 * @param degreesOfFreedom Degrees of freedom. 056 * @param inverseCumAccuracy the maximum absolute error in inverse 057 * cumulative probability estimates (defaults to 058 * {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}). 059 * @since 2.1 060 */ 061 public ChiSquaredDistribution(double degreesOfFreedom, 062 double inverseCumAccuracy) { 063 this(new Well19937c(), degreesOfFreedom, inverseCumAccuracy); 064 } 065 066 /** 067 * Create a Chi-Squared distribution with the given degrees of freedom and 068 * inverse cumulative probability accuracy. 069 * 070 * @param rng Random number generator. 071 * @param degreesOfFreedom Degrees of freedom. 072 * @param inverseCumAccuracy the maximum absolute error in inverse 073 * cumulative probability estimates (defaults to 074 * {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}). 075 * @since 3.1 076 */ 077 public ChiSquaredDistribution(RandomGenerator rng, 078 double degreesOfFreedom, 079 double inverseCumAccuracy) { 080 super(rng); 081 082 gamma = new GammaDistribution(degreesOfFreedom / 2, 2); 083 solverAbsoluteAccuracy = inverseCumAccuracy; 084 } 085 086 /** 087 * Access the number of degrees of freedom. 088 * 089 * @return the degrees of freedom. 090 */ 091 public double getDegreesOfFreedom() { 092 return gamma.getShape() * 2.0; 093 } 094 095 /** {@inheritDoc} */ 096 public double density(double x) { 097 return gamma.density(x); 098 } 099 100 /** {@inheritDoc} */ 101 public double cumulativeProbability(double x) { 102 return gamma.cumulativeProbability(x); 103 } 104 105 /** {@inheritDoc} */ 106 @Override 107 protected double getSolverAbsoluteAccuracy() { 108 return solverAbsoluteAccuracy; 109 } 110 111 /** 112 * {@inheritDoc} 113 * 114 * For {@code k} degrees of freedom, the mean is {@code k}. 115 */ 116 public double getNumericalMean() { 117 return getDegreesOfFreedom(); 118 } 119 120 /** 121 * {@inheritDoc} 122 * 123 * @return {@code 2 * k}, where {@code k} is the number of degrees of freedom. 124 */ 125 public double getNumericalVariance() { 126 return 2 * getDegreesOfFreedom(); 127 } 128 129 /** 130 * {@inheritDoc} 131 * 132 * The lower bound of the support is always 0 no matter the 133 * degrees of freedom. 134 * 135 * @return zero. 136 */ 137 public double getSupportLowerBound() { 138 return 0; 139 } 140 141 /** 142 * {@inheritDoc} 143 * 144 * The upper bound of the support is always positive infinity no matter the 145 * degrees of freedom. 146 * 147 * @return {@code Double.POSITIVE_INFINITY}. 148 */ 149 public double getSupportUpperBound() { 150 return Double.POSITIVE_INFINITY; 151 } 152 153 /** {@inheritDoc} */ 154 public boolean isSupportLowerBoundInclusive() { 155 return true; 156 } 157 158 /** {@inheritDoc} */ 159 public boolean isSupportUpperBoundInclusive() { 160 return false; 161 } 162 163 /** 164 * {@inheritDoc} 165 * 166 * The support of this distribution is connected. 167 * 168 * @return {@code true} 169 */ 170 public boolean isSupportConnected() { 171 return true; 172 } 173 }