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/RegularizedBetaFunction.html">
021 * Regularized Beta function</a>.
022 *
023 * <p>\[ I_x(a,b) = \frac{1}{B(a, b)} \int_0^x t^{a-1}\,(1-t)^{b-1}\,dt \]
024 *
025 * <p>where \( B(a, b) \) is the beta function.
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/beta.hpp>}.
029 *
030 * @see
031 * <a href="https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/sf_beta/ibeta_function.html">
032 * Boost C++ Incomplete Beta functions</a>
033 */
034public final class RegularizedBeta {
035
036    /** Private constructor. */
037    private RegularizedBeta() {
038        // intentionally empty.
039    }
040
041    /**
042     * Computes the value of the
043     * <a href="https://mathworld.wolfram.com/RegularizedBetaFunction.html">
044     * regularized beta function</a> I(x, a, b).
045     *
046     * <p>\[ I_x(a,b) = \frac{1}{B(a, b)} \int_0^x t^{a-1}\,(1-t)^{b-1}\,dt \]
047     *
048     * <p>where \( B(a, b) \) is the beta function.
049     *
050     * @param x Value.
051     * @param a Parameter {@code a}.
052     * @param b Parameter {@code b}.
053     * @return the regularized beta function \( I_x(a, b) \).
054     * @throws ArithmeticException if the series evaluation fails to converge.
055     */
056    public static double value(double x,
057                               double a,
058                               double b) {
059        return BoostBeta.ibeta(a, b, x);
060    }
061
062    /**
063     * Computes the value of the
064     * <a href="https://mathworld.wolfram.com/RegularizedBetaFunction.html">
065     * regularized beta function</a> I(x, a, b).
066     *
067     * <p>\[ I_x(a,b) = \frac{1}{B(a, b)} \int_0^x t^{a-1}\,(1-t)^{b-1}\,dt \]
068     *
069     * <p>where \( B(a, b) \) is the beta function.
070     *
071     * @param x the value.
072     * @param a Parameter {@code a}.
073     * @param b Parameter {@code b}.
074     * @param epsilon Tolerance in series evaluation.
075     * @param maxIterations Maximum number of iterations in series evaluation.
076     * @return the regularized beta function \( I_x(a, b) \).
077     * @throws ArithmeticException if the series evaluation fails to converge.
078     */
079    public static double value(double x,
080                               final double a,
081                               final double b,
082                               double epsilon,
083                               int maxIterations) {
084        return BoostBeta.ibeta(a, b, x, new Policy(epsilon, maxIterations));
085    }
086
087    /**
088     * Computes the complement of the
089     * <a href="https://mathworld.wolfram.com/RegularizedBetaFunction.html">
090     * regularized beta function</a> I(x, a, b).
091     *
092     * <p>\[ 1 - I_x(a,b) = I_{1-x}(b, a) \]
093     *
094     * @param x Value.
095     * @param a Parameter {@code a}.
096     * @param b Parameter {@code b}.
097     * @return the complement of the regularized beta function \( 1 - I_x(a, b) \).
098     * @throws ArithmeticException if the series evaluation fails to converge.
099     * @since 1.1
100     */
101    public static double complement(double x,
102                                    double a,
103                                    double b) {
104        return BoostBeta.ibetac(a, b, x);
105    }
106
107    /**
108     * Computes the complement of the
109     * <a href="https://mathworld.wolfram.com/RegularizedBetaFunction.html">
110     * regularized beta function</a> I(x, a, b).
111     *
112     * <p>\[ 1 - I_x(a,b) = I_{1-x}(b, a) \]
113     *
114     * @param x the value.
115     * @param a Parameter {@code a}.
116     * @param b Parameter {@code b}.
117     * @param epsilon Tolerance in series evaluation.
118     * @param maxIterations Maximum number of iterations in series evaluation.
119     * @return the complement of the regularized beta function \( 1 - I_x(a, b) \).
120     * @throws ArithmeticException if the series evaluation fails to converge.
121     * @since 1.1
122     */
123    public static double complement(double x,
124                                    final double a,
125                                    final double b,
126                                    double epsilon,
127                                    int maxIterations) {
128        return BoostBeta.ibetac(a, b, x, new Policy(epsilon, maxIterations));
129    }
130
131    /**
132     * Computes the derivative of the
133     * <a href="https://mathworld.wolfram.com/RegularizedBetaFunction.html">
134     * regularized beta function</a> I(x, a, b).
135     *
136     * <p>\[ \frac{\delta}{\delta x} I_x(a,b) = \frac{(1-x)^{b-1} x^{a-1}}{B(a, b)} \]
137     *
138     * <p>where \( B(a, b) \) is the beta function.
139     *
140     * <p>This function has uses in some statistical distributions.
141     *
142     * @param x Value.
143     * @param a Parameter {@code a}.
144     * @param b Parameter {@code b}.
145     * @return the derivative of the regularized beta function \( I_x(a, b) \).
146     * @throws ArithmeticException if the series evaluation fails to converge.
147     * @since 1.1
148     */
149    public static double derivative(double x,
150                                    double a,
151                                    double b) {
152        return BoostBeta.ibetaDerivative(a, b, x);
153    }
154}