WPILibC++ 2024.3.2
incomplete_beta.hpp
Go to the documentation of this file.
1/*################################################################################
2 ##
3 ## Copyright (C) 2016-2023 Keith O'Hara
4 ##
5 ## This file is part of the GCE-Math C++ library.
6 ##
7 ## Licensed under the Apache License, Version 2.0 (the "License");
8 ## you may not use this file except in compliance with the License.
9 ## You may obtain a copy of the License at
10 ##
11 ## http://www.apache.org/licenses/LICENSE-2.0
12 ##
13 ## Unless required by applicable law or agreed to in writing, software
14 ## distributed under the License is distributed on an "AS IS" BASIS,
15 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 ## See the License for the specific language governing permissions and
17 ## limitations under the License.
18 ##
19 ################################################################################*/
20
21/*
22 * compile-time incomplete beta function
23 *
24 * see eq. 18.5.17a in the Handbook of Continued Fractions for Special Functions
25 */
26
27#ifndef _gcem_incomplete_beta_HPP
28#define _gcem_incomplete_beta_HPP
29
30namespace gcem
31{
32
33namespace internal
34{
35
36template<typename T>
37constexpr T incomplete_beta_cf(const T a, const T b, const T z, const T c_j, const T d_j, const T f_j, const int depth) noexcept;
38
39//
40// coefficients; see eq. 18.5.17b
41
42template<typename T>
43constexpr
44T
45incomplete_beta_coef_even(const T a, const T b, const T z, const int k)
46noexcept
47{
48 return( -z*(a + k)*(a + b + k)/( (a + 2*k)*(a + 2*k + T(1)) ) );
49}
50
51template<typename T>
52constexpr
53T
54incomplete_beta_coef_odd(const T a, const T b, const T z, const int k)
55noexcept
56{
57 return( z*k*(b - k)/((a + 2*k - T(1))*(a + 2*k)) );
58}
59
60template<typename T>
61constexpr
62T
63incomplete_beta_coef(const T a, const T b, const T z, const int depth)
64noexcept
65{
66 return( !is_odd(depth) ? incomplete_beta_coef_even(a,b,z,depth/2) :
67 incomplete_beta_coef_odd(a,b,z,(depth+1)/2) );
68}
69
70//
71// update formulae for the modified Lentz method
72
73template<typename T>
74constexpr
75T
76incomplete_beta_c_update(const T a, const T b, const T z, const T c_j, const int depth)
77noexcept
78{
79 return( T(1) + incomplete_beta_coef(a,b,z,depth)/c_j );
80}
81
82template<typename T>
83constexpr
84T
85incomplete_beta_d_update(const T a, const T b, const T z, const T d_j, const int depth)
86noexcept
87{
88 return( T(1) / (T(1) + incomplete_beta_coef(a,b,z,depth)*d_j) );
89}
90
91//
92// convergence-type condition
93
94template<typename T>
95constexpr
96T
97incomplete_beta_decision(const T a, const T b, const T z, const T c_j, const T d_j, const T f_j, const int depth)
98noexcept
99{
100 return( // tolerance check
101 abs(c_j*d_j - T(1)) < GCEM_INCML_BETA_TOL ? f_j*c_j*d_j :
102 // max_iter check
103 depth < GCEM_INCML_BETA_MAX_ITER ? \
104 // if
105 incomplete_beta_cf(a,b,z,c_j,d_j,f_j*c_j*d_j,depth+1) :
106 // else
107 f_j*c_j*d_j );
108}
109
110template<typename T>
111constexpr
112T
113incomplete_beta_cf(const T a, const T b, const T z, const T c_j, const T d_j, const T f_j, const int depth)
114noexcept
115{
116 return incomplete_beta_decision(a,b,z,
117 incomplete_beta_c_update(a,b,z,c_j,depth),
118 incomplete_beta_d_update(a,b,z,d_j,depth),
119 f_j,depth);
120}
121
122//
123// x^a (1-x)^{b} / (a beta(a,b)) * cf
124
125template<typename T>
126constexpr
127T
128incomplete_beta_begin(const T a, const T b, const T z)
129noexcept
130{
131 return ( (exp(a*log(z) + b*log(T(1)-z) - lbeta(a,b)) / a) * \
132 incomplete_beta_cf(a,b,z,T(1),
133 incomplete_beta_d_update(a,b,z,T(1),0),
134 incomplete_beta_d_update(a,b,z,T(1),0),1)
135 );
136}
137
138template<typename T>
139constexpr
140T
141incomplete_beta_check(const T a, const T b, const T z)
142noexcept
143{
144 return( // NaN check
145 any_nan(a, b, z) ? \
147 // indistinguishable from zero
148 GCLIM<T>::min() > z ? \
149 T(0) :
150 // parameter check for performance
151 (a + T(1))/(a + b + T(2)) > z ? \
153 T(1) - incomplete_beta_begin(b,a,T(1) - z) );
154}
155
156template<typename T1, typename T2, typename T3, typename TC = common_return_t<T1,T2,T3>>
157constexpr
158TC
159incomplete_beta_type_check(const T1 a, const T2 b, const T3 p)
160noexcept
161{
162 return incomplete_beta_check(static_cast<TC>(a),
163 static_cast<TC>(b),
164 static_cast<TC>(p));
165}
166
167}
168
169/**
170 * Compile-time regularized incomplete beta function
171 *
172 * @param a a real-valued, non-negative input.
173 * @param b a real-valued, non-negative input.
174 * @param z a real-valued, non-negative input.
175 *
176 * @return computes the regularized incomplete beta function,
177 * \f[ \frac{\text{B}(z;\alpha,\beta)}{\text{B}(\alpha,\beta)} = \frac{1}{\text{B}(\alpha,\beta)}\int_0^z t^{a-1} (1-t)^{\beta-1} dt \f]
178 * using a continued fraction representation, found in the Handbook of Continued Fractions for Special Functions, and a modified Lentz method.
179 * \f[ \frac{\text{B}(z;\alpha,\beta)}{\text{B}(\alpha,\beta)} = \frac{z^{\alpha} (1-t)^{\beta}}{\alpha \text{B}(\alpha,\beta)} \dfrac{a_1}{1 + \dfrac{a_2}{1 + \dfrac{a_3}{1 + \dfrac{a_4}{1 + \ddots}}}} \f]
180 * where \f$ a_1 = 1 \f$ and
181 * \f[ a_{2m+2} = - \frac{(\alpha + m)(\alpha + \beta + m)}{(\alpha + 2m)(\alpha + 2m + 1)}, \ m \geq 0 \f]
182 * \f[ a_{2m+1} = \frac{m(\beta - m)}{(\alpha + 2m - 1)(\alpha + 2m)}, \ m \geq 1 \f]
183 * The Lentz method works as follows: let \f$ f_j \f$ denote the value of the continued fraction up to the first \f$ j \f$ terms; \f$ f_j \f$ is updated as follows:
184 * \f[ c_j = 1 + a_j / c_{j-1}, \ \ d_j = 1 / (1 + a_j d_{j-1}) \f]
185 * \f[ f_j = c_j d_j f_{j-1} \f]
186 */
187
188template<typename T1, typename T2, typename T3>
189constexpr
190common_return_t<T1,T2,T3>
191incomplete_beta(const T1 a, const T2 b, const T3 z)
192noexcept
193{
195}
196
197}
198
199#endif
#define GCEM_INCML_BETA_TOL
Definition: gcem_options.hpp:161
#define GCEM_INCML_BETA_MAX_ITER
Definition: gcem_options.hpp:165
constexpr T incomplete_beta_decision(const T a, const T b, const T z, const T c_j, const T d_j, const T f_j, const int depth) noexcept
Definition: incomplete_beta.hpp:97
constexpr T incomplete_beta_coef_odd(const T a, const T b, const T z, const int k) noexcept
Definition: incomplete_beta.hpp:54
constexpr T incomplete_beta_coef_even(const T a, const T b, const T z, const int k) noexcept
Definition: incomplete_beta.hpp:45
constexpr TC incomplete_beta_type_check(const T1 a, const T2 b, const T3 p) noexcept
Definition: incomplete_beta.hpp:159
constexpr T incomplete_beta_cf(const T a, const T b, const T z, const T c_j, const T d_j, const T f_j, const int depth) noexcept
Definition: incomplete_beta.hpp:113
constexpr bool any_nan(const T1 x, const T2 y) noexcept
Definition: is_nan.hpp:48
constexpr T incomplete_beta_check(const T a, const T b, const T z) noexcept
Definition: incomplete_beta.hpp:141
constexpr T incomplete_beta_coef(const T a, const T b, const T z, const int depth) noexcept
Definition: incomplete_beta.hpp:63
constexpr T incomplete_beta_c_update(const T a, const T b, const T z, const T c_j, const int depth) noexcept
Definition: incomplete_beta.hpp:76
constexpr bool is_odd(const llint_t x) noexcept
Definition: is_odd.hpp:36
constexpr T incomplete_beta_begin(const T a, const T b, const T z) noexcept
Definition: incomplete_beta.hpp:128
constexpr T incomplete_beta_d_update(const T a, const T b, const T z, const T d_j, const int depth) noexcept
Definition: incomplete_beta.hpp:85
Definition: is_even.hpp:29
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition: abs.hpp:40
constexpr common_return_t< T1, T2, T3 > incomplete_beta(const T1 a, const T2 b, const T3 z) noexcept
Compile-time regularized incomplete beta function.
Definition: incomplete_beta.hpp:191
constexpr return_t< T > log(const T x) noexcept
Compile-time natural logarithm function.
Definition: log.hpp:186
std::numeric_limits< T > GCLIM
Definition: gcem_options.hpp:74
constexpr common_return_t< T1, T2 > lbeta(const T1 a, const T2 b) noexcept
Compile-time log-beta function.
Definition: lbeta.hpp:39
b
Definition: data.h:44