WPILibC++ 2024.3.2
incomplete_gamma.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 (regularized) incomplete gamma function
23 */
24
25#ifndef _gcem_incomplete_gamma_HPP
26#define _gcem_incomplete_gamma_HPP
27
28namespace gcem
29{
30
31namespace internal
32{
33
34// 50 point Gauss-Legendre quadrature
35
36template<typename T>
37constexpr
38T
39incomplete_gamma_quad_inp_vals(const T lb, const T ub, const int counter)
40noexcept
41{
42 return (ub-lb) * gauss_legendre_50_points[counter] / T(2) + (ub + lb) / T(2);
43}
44
45template<typename T>
46constexpr
47T
48incomplete_gamma_quad_weight_vals(const T lb, const T ub, const int counter)
49noexcept
50{
51 return (ub-lb) * gauss_legendre_50_weights[counter] / T(2);
52}
53
54template<typename T>
55constexpr
56T
57incomplete_gamma_quad_fn(const T x, const T a, const T lg_term)
58noexcept
59{
60 return exp( -x + (a-T(1))*log(x) - lg_term );
61}
62
63template<typename T>
64constexpr
65T
66incomplete_gamma_quad_recur(const T lb, const T ub, const T a, const T lg_term, const int counter)
67noexcept
68{
69 return( counter < 49 ? \
70 // if
73 + incomplete_gamma_quad_recur(lb,ub,a,lg_term,counter+1) :
74 // else
77}
78
79template<typename T>
80constexpr
81T
82incomplete_gamma_quad_lb(const T a, const T z)
83noexcept
84{
85 return( a > T(1000) ? max(T(0),min(z,a) - 11*sqrt(a)) : // break integration into ranges
86 a > T(800) ? max(T(0),min(z,a) - 11*sqrt(a)) :
87 a > T(500) ? max(T(0),min(z,a) - 10*sqrt(a)) :
88 a > T(300) ? max(T(0),min(z,a) - 10*sqrt(a)) :
89 a > T(100) ? max(T(0),min(z,a) - 9*sqrt(a)) :
90 a > T(90) ? max(T(0),min(z,a) - 9*sqrt(a)) :
91 a > T(70) ? max(T(0),min(z,a) - 8*sqrt(a)) :
92 a > T(50) ? max(T(0),min(z,a) - 7*sqrt(a)) :
93 a > T(40) ? max(T(0),min(z,a) - 6*sqrt(a)) :
94 a > T(30) ? max(T(0),min(z,a) - 5*sqrt(a)) :
95 // else
96 max(T(0),min(z,a)-4*sqrt(a)) );
97}
98
99template<typename T>
100constexpr
101T
102incomplete_gamma_quad_ub(const T a, const T z)
103noexcept
104{
105 return( a > T(1000) ? min(z, a + 10*sqrt(a)) :
106 a > T(800) ? min(z, a + 10*sqrt(a)) :
107 a > T(500) ? min(z, a + 9*sqrt(a)) :
108 a > T(300) ? min(z, a + 9*sqrt(a)) :
109 a > T(100) ? min(z, a + 8*sqrt(a)) :
110 a > T(90) ? min(z, a + 8*sqrt(a)) :
111 a > T(70) ? min(z, a + 7*sqrt(a)) :
112 a > T(50) ? min(z, a + 6*sqrt(a)) :
113 // else
114 min(z, a + 5*sqrt(a)) );
115}
116
117template<typename T>
118constexpr
119T
120incomplete_gamma_quad(const T a, const T z)
121noexcept
122{
124}
125
126// reverse cf expansion
127// see: https://functions.wolfram.com/GammaBetaErf/Gamma2/10/0003/
128
129template<typename T>
130constexpr
131T
132incomplete_gamma_cf_2_recur(const T a, const T z, const int depth)
133noexcept
134{
135 return( depth < 100 ? \
136 // if
137 (1 + (depth-1)*2 - a + z) + depth*(a - depth)/incomplete_gamma_cf_2_recur(a,z,depth+1) :
138 // else
139 (1 + (depth-1)*2 - a + z) );
140}
141
142template<typename T>
143constexpr
144T
145incomplete_gamma_cf_2(const T a, const T z)
146noexcept
147{ // lower (regularized) incomplete gamma function
148 return( T(1.0) - exp(a*log(z) - z - lgamma(a)) / incomplete_gamma_cf_2_recur(a,z,1) );
149}
150
151// cf expansion
152// see: http://functions.wolfram.com/GammaBetaErf/Gamma2/10/0009/
153
154template<typename T>
155constexpr
156T
157incomplete_gamma_cf_1_coef(const T a, const T z, const int depth)
158noexcept
159{
160 return( is_odd(depth) ? - (a - 1 + T(depth+1)/T(2)) * z : T(depth)/T(2) * z );
161}
162
163template<typename T>
164constexpr
165T
166incomplete_gamma_cf_1_recur(const T a, const T z, const int depth)
167noexcept
168{
169 return( depth < GCEM_INCML_GAMMA_MAX_ITER ? \
170 // if
171 (a + depth - 1) + incomplete_gamma_cf_1_coef(a,z,depth)/incomplete_gamma_cf_1_recur(a,z,depth+1) :
172 // else
173 (a + depth - 1) );
174}
175
176template<typename T>
177constexpr
178T
179incomplete_gamma_cf_1(const T a, const T z)
180noexcept
181{ // lower (regularized) incomplete gamma function
182 return( exp(a*log(z) - z - lgamma(a)) / incomplete_gamma_cf_1_recur(a,z,1) );
183}
184
185//
186
187template<typename T>
188constexpr
189T
190incomplete_gamma_check(const T a, const T z)
191noexcept
192{
193 return( // NaN check
194 any_nan(a, z) ? \
196 //
197 a < T(0) ? \
199 //
200 GCLIM<T>::min() > z ? \
201 T(0) :
202 //
203 GCLIM<T>::min() > a ? \
204 T(1) :
205 // cf or quadrature
206 (a < T(10)) && (z - a < T(10)) ?
208 (a < T(10)) || (z/a > T(3)) ?
210 // else
212}
213
214template<typename T1, typename T2, typename TC = common_return_t<T1,T2>>
215constexpr
216TC
217incomplete_gamma_type_check(const T1 a, const T2 p)
218noexcept
219{
220 return incomplete_gamma_check(static_cast<TC>(a),
221 static_cast<TC>(p));
222}
223
224}
225
226/**
227 * Compile-time regularized lower incomplete gamma function
228 *
229 * @param a a real-valued, non-negative input.
230 * @param x a real-valued, non-negative input.
231 *
232 * @return the regularized lower incomplete gamma function evaluated at (\c a, \c x),
233 * \f[ \frac{\gamma(a,x)}{\Gamma(a)} = \frac{1}{\Gamma(a)} \int_0^x t^{a-1} \exp(-t) dt \f]
234 * When \c a is not too large, the value is computed using the continued fraction representation of the upper incomplete gamma function, \f$ \Gamma(a,x) \f$, using
235 * \f[ \Gamma(a,x) = \Gamma(a) - \dfrac{x^a\exp(-x)}{a - \dfrac{ax}{a + 1 + \dfrac{x}{a + 2 - \dfrac{(a+1)x}{a + 3 + \dfrac{2x}{a + 4 - \ddots}}}}} \f]
236 * where \f$ \gamma(a,x) \f$ and \f$ \Gamma(a,x) \f$ are connected via
237 * \f[ \frac{\gamma(a,x)}{\Gamma(a)} + \frac{\Gamma(a,x)}{\Gamma(a)} = 1 \f]
238 * When \f$ a > 10 \f$, a 50-point Gauss-Legendre quadrature scheme is employed.
239 */
240
241template<typename T1, typename T2>
242constexpr
243common_return_t<T1,T2>
244incomplete_gamma(const T1 a, const T2 x)
245noexcept
246{
248}
249
250}
251
252#endif
#define GCEM_INCML_GAMMA_MAX_ITER
Definition: gcem_options.hpp:173
constexpr T incomplete_gamma_check(const T a, const T z) noexcept
Definition: incomplete_gamma.hpp:190
constexpr T incomplete_gamma_quad_weight_vals(const T lb, const T ub, const int counter) noexcept
Definition: incomplete_gamma.hpp:48
constexpr T incomplete_gamma_quad_recur(const T lb, const T ub, const T a, const T lg_term, const int counter) noexcept
Definition: incomplete_gamma.hpp:66
constexpr T incomplete_gamma_cf_1_coef(const T a, const T z, const int depth) noexcept
Definition: incomplete_gamma.hpp:157
constexpr bool any_nan(const T1 x, const T2 y) noexcept
Definition: is_nan.hpp:48
constexpr T incomplete_gamma_quad_ub(const T a, const T z) noexcept
Definition: incomplete_gamma.hpp:102
constexpr T incomplete_gamma_quad_lb(const T a, const T z) noexcept
Definition: incomplete_gamma.hpp:82
constexpr bool is_odd(const llint_t x) noexcept
Definition: is_odd.hpp:36
constexpr T incomplete_gamma_cf_2_recur(const T a, const T z, const int depth) noexcept
Definition: incomplete_gamma.hpp:132
constexpr T incomplete_gamma_quad_fn(const T x, const T a, const T lg_term) noexcept
Definition: incomplete_gamma.hpp:57
constexpr T incomplete_gamma_cf_1_recur(const T a, const T z, const int depth) noexcept
Definition: incomplete_gamma.hpp:166
constexpr T incomplete_gamma_quad(const T a, const T z) noexcept
Definition: incomplete_gamma.hpp:120
constexpr TC incomplete_gamma_type_check(const T1 a, const T2 p) noexcept
Definition: incomplete_gamma.hpp:217
constexpr T incomplete_gamma_quad_inp_vals(const T lb, const T ub, const int counter) noexcept
Definition: incomplete_gamma.hpp:39
constexpr T incomplete_gamma_cf_2(const T a, const T z) noexcept
Definition: incomplete_gamma.hpp:145
constexpr T incomplete_gamma_cf_1(const T a, const T z) noexcept
Definition: incomplete_gamma.hpp:179
Definition: is_even.hpp:29
static const long double gauss_legendre_50_points[50]
Definition: gauss_legendre_50.hpp:28
constexpr common_t< T1, T2 > max(const T1 x, const T2 y) noexcept
Compile-time pairwise maximum function.
Definition: max.hpp:41
constexpr common_return_t< T1, T2 > incomplete_gamma(const T1 a, const T2 x) noexcept
Compile-time regularized lower incomplete gamma function.
Definition: incomplete_gamma.hpp:244
constexpr return_t< T > lgamma(const T x) noexcept
Compile-time log-gamma function.
Definition: lgamma.hpp:135
constexpr return_t< T > log(const T x) noexcept
Compile-time natural logarithm function.
Definition: log.hpp:186
constexpr return_t< T > sqrt(const T x) noexcept
Compile-time square-root function.
Definition: sqrt.hpp:109
static const long double gauss_legendre_50_weights[50]
Definition: gauss_legendre_50.hpp:82
constexpr common_t< T1, T2 > min(const T1 x, const T2 y) noexcept
Compile-time pairwise minimum function.
Definition: min.hpp:41
std::numeric_limits< T > GCLIM
Definition: gcem_options.hpp:74
lb
Definition: mass.h:44