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.numbers.gamma;
018
019/**
020 * <a href="https://mathworld.wolfram.com/RegularizedGammaFunction.html">
021 * Regularized Gamma functions</a>.
022 *
023 * <p>By definition, the lower and upper regularized gamma functions satisfy:
024 *
025 * <p>\[ 1 = P(a, x) + Q(a, x) \]
026 *
027 * <p>This code has been adapted from the <a href="https://www.boost.org/">Boost</a>
028 * {@code c++} implementation {@code <boost/math/special_functions/gamma.hpp>}.
029 *
030 * @see
031 * <a href="https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html">
032 * Boost C++ Incomplete Gamma functions</a>
033 */
034public final class RegularizedGamma {
035    /** Private constructor. */
036    private RegularizedGamma() {
037        // intentionally empty.
038    }
039
040    /**
041     * <a href="http://mathworld.wolfram.com/RegularizedGammaFunction.html">
042     * Lower regularized Gamma function</a> \( P(a, x) \).
043     *
044     * <p>\[ P(a,x) = 1 - Q(a,x) = \frac{\gamma(a,x)}{\Gamma(a)} = \frac{1}{\Gamma(a)} \int_0^x t^{a-1}\,e^{-t}\,dt \]
045     */
046    public static final class P {
047        /** Prevent instantiation. */
048        private P() {}
049
050        /**
051         * Computes the lower regularized gamma function \( P(a, x) \).
052         *
053         * @param a Argument.
054         * @param x Argument.
055         * @return \( P(a, x) \).
056         * @throws ArithmeticException if the continued fraction fails to converge.
057         */
058        public static double value(double a,
059                                   double x) {
060            return BoostGamma.gammaP(a, x);
061        }
062
063        /**
064         * Computes the lower regularized gamma function \( P(a, x) \).
065         *
066         * @param a Argument.
067         * @param x Argument.
068         * @param epsilon Tolerance in series evaluation.
069         * @param maxIterations Maximum number of iterations in series evaluation.
070         * @return \( P(a, x) \).
071         * @throws ArithmeticException if the series evaluation fails to converge.
072         */
073        public static double value(double a,
074                                   double x,
075                                   double epsilon,
076                                   int maxIterations) {
077            return BoostGamma.gammaP(a, x, new Policy(epsilon, maxIterations));
078        }
079
080        /**
081         * Computes the derivative of the lower regularized gamma function \( P(a, x) \).
082         *
083         * <p>\[ \frac{\delta}{\delta x} P(a,x) = \frac{e^{-x} x^{a-1}}{\Gamma(a)} \]
084         *
085         * <p>This function has uses in some statistical distributions.
086         *
087         * @param a Argument.
088         * @param x Argument.
089         * @return derivative of \( P(a,x) \) with respect to x.
090         * @since 1.1
091         */
092        public static double derivative(double a,
093                                        double x) {
094            return BoostGamma.gammaPDerivative(a, x);
095        }
096    }
097
098    /**
099     * <a href="http://mathworld.wolfram.com/RegularizedGammaFunction.html">
100     * Upper regularized Gamma function</a> \( Q(a, x) \).
101     *
102     * <p>\[ Q(a,x) = 1 - P(a,x) = \frac{\Gamma(a,x)}{\Gamma(a)} = \frac{1}{\Gamma(a)} \int_x^{\infty} t^{a-1}\,e^{-t}\,dt \]
103     */
104    public static final class Q {
105        /** Prevent instantiation. */
106        private Q() {}
107
108        /**
109         * Computes the upper regularized gamma function \( Q(a, x) \).
110         *
111         * @param a Argument.
112         * @param x Argument.
113         * @return \( Q(a, x) \).
114         * @throws ArithmeticException if the series evaluation fails to converge.
115         */
116        public static double value(double a,
117                                   double x) {
118            return BoostGamma.gammaQ(a, x);
119        }
120
121        /**
122         * Computes the upper regularized gamma function \( Q(a, x) \).
123         *
124         * @param a Argument.
125         * @param x Argument.
126         * @param epsilon Tolerance in series evaluation.
127         * @param maxIterations Maximum number of iterations in series evaluation.
128         * @return \( Q(a, x) \).
129         * @throws ArithmeticException if the series evaluation fails to converge.
130         */
131        public static double value(final double a,
132                                   double x,
133                                   double epsilon,
134                                   int maxIterations) {
135            return BoostGamma.gammaQ(a, x, new Policy(epsilon, maxIterations));
136        }
137
138        /**
139         * Computes the derivative of the upper regularized gamma function \( Q(a, x) \).
140         *
141         * <p>\[ \frac{\delta}{\delta x} Q(a,x) = -\frac{e^{-x} x^{a-1}}{\Gamma(a)} \]
142         *
143         * <p>This function has uses in some statistical distributions.
144         *
145         * @param a Argument.
146         * @param x Argument.
147         * @return derivative of \( Q(a,x) \) with respect to x.
148         * @since 1.1
149         */
150        public static double derivative(double a,
151                                        double x) {
152            return -BoostGamma.gammaPDerivative(a, x);
153        }
154    }
155}