1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/*
2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more
3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements.  See the NOTICE file distributed with
4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership.
5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0
6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with
7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License.  You may obtain a copy of the License at
8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *      http://www.apache.org/licenses/LICENSE-2.0
10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software
12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS,
13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and
15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License.
16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.distribution;
18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.Serializable;
20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathException;
22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException;
23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats;
24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.random.RandomDataImpl;
25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.FastMath;
26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/**
29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Base class for integer-valued discrete distributions.  Default
30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * implementations are provided for some of the methods that do not vary
31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * from distribution to distribution.
32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1067494 $ $Date: 2011-02-05 20:49:07 +0100 (sam. 05 févr. 2011) $
34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic abstract class AbstractIntegerDistribution extends AbstractDistribution
36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    implements IntegerDistribution, Serializable {
37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   /** Serializable version identifier */
39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long serialVersionUID = -1146319659338487221L;
40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * RandomData instance used to generate samples from the distribution
43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected final RandomDataImpl randomData = new RandomDataImpl();
46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Default constructor.
49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected AbstractIntegerDistribution() {
51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        super();
52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For a random variable X whose values are distributed according
56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to this distribution, this method returns P(X ≤ x).  In other words,
57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * this method represents the  (cumulative) distribution function, or
58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * CDF, for this distribution.
59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If <code>x</code> does not represent an integer value, the CDF is
61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * evaluated at the greatest integer less than x.
62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x the value at which the distribution function is evaluated.
64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return cumulative probability that a random variable with this
65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * distribution takes a value less than or equal to <code>x</code>
66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if the cumulative probability can not be
67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * computed due to convergence or other numerical errors.
68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double cumulativeProbability(double x) throws MathException {
70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return cumulativeProbability((int) FastMath.floor(x));
71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For a random variable X whose values are distributed according
75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to this distribution, this method returns P(x0 &le; X &le; x1).
76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x0 the (inclusive) lower bound
78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x1 the (inclusive) upper bound
79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the probability that a random variable with this distribution
80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * will take a value between <code>x0</code> and <code>x1</code>,
81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * including the endpoints.
82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if the cumulative probability can not be
83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * computed due to convergence or other numerical errors.
84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>x0 > x1</code>
85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double cumulativeProbability(double x0, double x1)
88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        throws MathException {
89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x0 > x1) {
90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                  LocalizedFormats.LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT, x0, x1);
92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (FastMath.floor(x0) < x0) {
94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return cumulativeProbability(((int) FastMath.floor(x0)) + 1,
95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               (int) FastMath.floor(x1)); // don't want to count mass below x0
96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else { // x0 is mathematical integer, so use as is
97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return cumulativeProbability((int) FastMath.floor(x0),
98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                (int) FastMath.floor(x1));
99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For a random variable X whose values are distributed according
104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to this distribution, this method returns P(X &le; x).  In other words,
105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * this method represents the probability distribution function, or PDF,
106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * for this distribution.
107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x the value at which the PDF is evaluated.
109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return PDF for this distribution.
110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if the cumulative probability can not be
111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            computed due to convergence or other numerical errors.
112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public abstract double cumulativeProbability(int x) throws MathException;
114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For a random variable X whose values are distributed according
117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to this distribution, this method returns P(X = x). In other words, this
118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * method represents the probability mass function,  or PMF, for the distribution.
119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>
120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * If <code>x</code> does not represent an integer value, 0 is returned.
121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x the value at which the probability density function is evaluated
123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the value of the probability density function at x
124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double probability(double x) {
126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double fl = FastMath.floor(x);
127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (fl == x) {
128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return this.probability((int) x);
129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return 0;
131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    * For a random variable X whose values are distributed according
136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to this distribution, this method returns P(x0 &le; X &le; x1).
137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x0 the inclusive, lower bound
139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x1 the inclusive, upper bound
140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the cumulative probability.
141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if the cumulative probability can not be
142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            computed due to convergence or other numerical errors.
143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if x0 > x1
144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double cumulativeProbability(int x0, int x1) throws MathException {
146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x0 > x1) {
147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                  LocalizedFormats.LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT, x0, x1);
149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return cumulativeProbability(x1) - cumulativeProbability(x0 - 1);
151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For a random variable X whose values are distributed according
155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * to this distribution, this method returns the largest x, such
156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * that P(X &le; x) &le; <code>p</code>.
157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param p the desired probability
159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the largest x such that P(X &le; x) <= p
160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if the inverse cumulative probability can not be
161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            computed due to convergence or other numerical errors.
162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if p < 0 or p > 1
163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int inverseCumulativeProbability(final double p) throws MathException{
165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (p < 0.0 || p > 1.0) {
166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                  LocalizedFormats.OUT_OF_RANGE_SIMPLE, p, 0.0, 1.0);
168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // by default, do simple bisection.
171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // subclasses can override if there is a better method.
172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int x0 = getDomainLowerBound(p);
173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int x1 = getDomainUpperBound(p);
174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double pm;
175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (x0 < x1) {
176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int xm = x0 + (x1 - x0) / 2;
177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            pm = checkedCumulativeProbability(xm);
178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (pm > p) {
179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // update x1
180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (xm == x1) {
181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // this can happen with integer division
182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // simply decrement x1
183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    --x1;
184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                } else {
185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // update x1 normally
186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    x1 = xm;
187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                // update x0
190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                if (xm == x0) {
191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // this can happen with integer division
192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // simply increment x0
193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    ++x0;
194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                } else {
195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    // update x0 normally
196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    x0 = xm;
197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                }
198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        // insure x0 is the correct critical point
202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        pm = checkedCumulativeProbability(x0);
203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (pm > p) {
204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            --x0;
205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            pm = checkedCumulativeProbability(x0);
206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return x0;
209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Reseeds the random generator used to generate samples.
213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param seed the new seed
215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void reseedRandomGenerator(long seed) {
218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        randomData.reSeed(seed);
219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Generates a random value sampled from this distribution. The default
223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * implementation uses the
224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <a href="http://en.wikipedia.org/wiki/Inverse_transform_sampling"> inversion method.</a>
225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return random value
227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if an error occurs generating the random value
229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int sample() throws MathException {
231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return randomData.nextInversionDeviate(this);
232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Generates a random sample from the distribution.  The default implementation
236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * generates the sample by calling {@link #sample()} in a loop.
237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param sampleSize number of random values to generate
239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return an array representing the random sample
241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if an error occurs generating the sample
242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if sampleSize is not positive
243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int[] sample(int sampleSize) throws MathException {
245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (sampleSize <= 0) {
246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            MathRuntimeException.createIllegalArgumentException(LocalizedFormats.NOT_POSITIVE_SAMPLE_SIZE, sampleSize);
247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int[] out = new int[sampleSize];
249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < sampleSize; i++) {
250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            out[i] = sample();
251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return out;
253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Computes the cumulative probability function and checks for NaN values returned.
257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Throws MathException if the value is NaN. Rethrows any MathException encountered
258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * evaluating the cumulative probability function. Throws
259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * MathException if the cumulative probability function returns NaN.
260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param argument input value
262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return cumulative probability
263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws MathException if the cumulative probability is NaN
264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private double checkedCumulativeProbability(int argument) throws MathException {
266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double result = Double.NaN;
267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = cumulativeProbability(argument);
268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (Double.isNaN(result)) {
269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw new MathException(LocalizedFormats.DISCRETE_CUMULATIVE_PROBABILITY_RETURNED_NAN, argument);
270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Access the domain value lower bound, based on <code>p</code>, used to
276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * bracket a PDF root.  This method is used by
277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@link #inverseCumulativeProbability(double)} to find critical values.
278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param p the desired probability for the critical value
280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return domain value lower bound, i.e.
281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected abstract int getDomainLowerBound(double p);
284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Access the domain value upper bound, based on <code>p</code>, used to
287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * bracket a PDF root.  This method is used by
288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@link #inverseCumulativeProbability(double)} to find critical values.
289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param p the desired probability for the critical value
291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return domain value upper bound, i.e.
292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected abstract int getDomainUpperBound(double p);
295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Use this method to get information about whether the lower bound
298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * of the support is inclusive or not. For discrete support,
299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * only true here is meaningful.
300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return true (always but at Integer.MIN_VALUE because of the nature of discrete support)
302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public boolean isSupportLowerBoundInclusive() {
305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return true;
306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Use this method to get information about whether the upper bound
310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * of the support is inclusive or not. For discrete support,
311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * only true here is meaningful.
312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return true (always but at Integer.MAX_VALUE because of the nature of discrete support)
314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public boolean isSupportUpperBoundInclusive() {
317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return true;
318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond}
320