WPILibC++ 2024.3.2
incomplete_gamma_inv.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 * inverse of the incomplete gamma function
23 */
24
25#ifndef _gcem_incomplete_gamma_inv_HPP
26#define _gcem_incomplete_gamma_inv_HPP
27
28namespace gcem
29{
30
31namespace internal
32{
33
34template<typename T>
35constexpr T incomplete_gamma_inv_decision(const T value, const T a, const T p, const T direc, const T lg_val, const int iter_count) noexcept;
36
37//
38// initial value for Halley
39
40template<typename T>
41constexpr
42T
44noexcept
45{ // a > 1.0
46 return( p > T(0.5) ? sqrt(-2*log(T(1) - p)) : sqrt(-2*log(p)) );
47}
48
49template<typename T>
50constexpr
51T
53noexcept
54{ // a <= 1.0
55 return( T(1) - T(0.253) * a - T(0.12) * a*a );
56}
57
58//
59
60template<typename T>
61constexpr
62T
64noexcept
65{ // internal for a > 1.0
66 return( t_val - (T(2.515517L) + T(0.802853L)*t_val + T(0.010328L)*t_val*t_val) \
67 / (T(1) + T(1.432788L)*t_val + T(0.189269L)*t_val*t_val + T(0.001308L)*t_val*t_val*t_val) );
68}
69
70template<typename T>
71constexpr
72T
73incomplete_gamma_inv_initial_val_1_int_end(const T value_inp, const T a)
74noexcept
75{ // internal for a > 1.0
76 return max( T(1E-04), a*pow(T(1) - T(1)/(9*a) - value_inp/(3*sqrt(a)), 3) );
77}
78
79template<typename T>
80constexpr
81T
82incomplete_gamma_inv_initial_val_1(const T a, const T t_val, const T sgn_term)
83noexcept
84{ // a > 1.0
86}
87
88template<typename T>
89constexpr
90T
91incomplete_gamma_inv_initial_val_2(const T a, const T p, const T t_val)
92noexcept
93{ // a <= 1.0
94 return( p < t_val ? \
95 // if
96 pow(p/t_val,T(1)/a) :
97 // else
98 T(1) - log(T(1) - (p - t_val)/(T(1) - t_val)) );
99}
100
101// initial value
102
103template<typename T>
104constexpr
105T
107noexcept
108{
109 return( a > T(1) ? \
110 // if
113 p > T(0.5) ? T(-1) : T(1)) :
114 // else
117}
118
119//
120// Halley recursion
121
122template<typename T>
123constexpr
124T
125incomplete_gamma_inv_err_val(const T value, const T a, const T p)
126noexcept
127{ // err_val = f(x)
128 return( incomplete_gamma(a,value) - p );
129}
130
131template<typename T>
132constexpr
133T
134incomplete_gamma_inv_deriv_1(const T value, const T a, const T lg_val)
135noexcept
136{ // derivative of the incomplete gamma function w.r.t. x
137 return( exp( - value + (a - T(1))*log(value) - lg_val ) );
138}
139
140template<typename T>
141constexpr
142T
143incomplete_gamma_inv_deriv_2(const T value, const T a, const T deriv_1)
144noexcept
145{ // second derivative of the incomplete gamma function w.r.t. x
146 return( deriv_1*((a - T(1))/value - T(1)) );
147}
148
149template<typename T>
150constexpr
151T
152incomplete_gamma_inv_ratio_val_1(const T value, const T a, const T p, const T deriv_1)
153noexcept
154{
155 return( incomplete_gamma_inv_err_val(value,a,p) / deriv_1 );
156}
157
158template<typename T>
159constexpr
160T
161incomplete_gamma_inv_ratio_val_2(const T value, const T a, const T deriv_1)
162noexcept
163{
164 return( incomplete_gamma_inv_deriv_2(value,a,deriv_1) / deriv_1 );
165}
166
167template<typename T>
168constexpr
169T
170incomplete_gamma_inv_halley(const T ratio_val_1, const T ratio_val_2)
171noexcept
172{
173 return( ratio_val_1 / max( T(0.8), min( T(1.2), T(1) - T(0.5)*ratio_val_1*ratio_val_2 ) ) );
174}
175
176template<typename T>
177constexpr
178T
179incomplete_gamma_inv_recur(const T value, const T a, const T p, const T deriv_1, const T lg_val, const int iter_count)
180noexcept
181{
182 return incomplete_gamma_inv_decision(value, a, p,
184 incomplete_gamma_inv_ratio_val_2(value,a,deriv_1)),
185 lg_val, iter_count);
186}
187
188template<typename T>
189constexpr
190T
191incomplete_gamma_inv_decision(const T value, const T a, const T p, const T direc, const T lg_val, const int iter_count)
192noexcept
193{
194 // return( abs(direc) > GCEM_INCML_GAMMA_INV_TOL ? incomplete_gamma_inv_recur(value - direc, a, p, incomplete_gamma_inv_deriv_1(value,a,lg_val), lg_val) : value - direc );
195 return( iter_count <= GCEM_INCML_GAMMA_INV_MAX_ITER ? \
196 // if
197 incomplete_gamma_inv_recur(value-direc,a,p,
198 incomplete_gamma_inv_deriv_1(value,a,lg_val),
199 lg_val,iter_count+1) :
200 // else
201 value - direc );
202}
203
204template<typename T>
205constexpr
206T
207incomplete_gamma_inv_begin(const T initial_val, const T a, const T p, const T lg_val)
208noexcept
209{
210 return incomplete_gamma_inv_recur(initial_val,a,p,
211 incomplete_gamma_inv_deriv_1(initial_val,a,lg_val), lg_val,1);
212}
213
214template<typename T>
215constexpr
216T
217incomplete_gamma_inv_check(const T a, const T p)
218noexcept
219{
220 return( // NaN check
221 any_nan(a, p) ? \
223 //
224 GCLIM<T>::min() > p ? \
225 T(0) :
226 p > T(1) ? \
228 GCLIM<T>::min() > abs(T(1) - p) ? \
230 //
231 GCLIM<T>::min() > a ? \
232 T(0) :
233 // else
235}
236
237template<typename T1, typename T2, typename TC = common_return_t<T1,T2>>
238constexpr
239TC
240incomplete_gamma_inv_type_check(const T1 a, const T2 p)
241noexcept
242{
243 return incomplete_gamma_inv_check(static_cast<TC>(a),
244 static_cast<TC>(p));
245}
246
247}
248
249/**
250 * Compile-time inverse incomplete gamma function
251 *
252 * @param a a real-valued, non-negative input.
253 * @param p a real-valued input with values in the unit-interval.
254 *
255 * @return Computes the inverse incomplete gamma function, a value \f$ x \f$ such that
256 * \f[ f(x) := \frac{\gamma(a,x)}{\Gamma(a)} - p \f]
257 * equal to zero, for a given \c p.
258 * GCE-Math finds this root using Halley's method:
259 * \f[ x_{n+1} = x_n - \frac{f(x_n)/f'(x_n)}{1 - 0.5 \frac{f(x_n)}{f'(x_n)} \frac{f''(x_n)}{f'(x_n)} } \f]
260 * where
261 * \f[ \frac{\partial}{\partial x} \left(\frac{\gamma(a,x)}{\Gamma(a)}\right) = \frac{1}{\Gamma(a)} x^{a-1} \exp(-x) \f]
262 * \f[ \frac{\partial^2}{\partial x^2} \left(\frac{\gamma(a,x)}{\Gamma(a)}\right) = \frac{1}{\Gamma(a)} x^{a-1} \exp(-x) \left( \frac{a-1}{x} - 1 \right) \f]
263 */
264
265template<typename T1, typename T2>
266constexpr
267common_return_t<T1,T2>
268incomplete_gamma_inv(const T1 a, const T2 p)
269noexcept
270{
272}
273
274}
275
276#endif
#define GCEM_INCML_GAMMA_INV_MAX_ITER
Definition: gcem_options.hpp:177
constexpr T incomplete_gamma_inv_t_val_2(const T a) noexcept
Definition: incomplete_gamma_inv.hpp:52
constexpr T incomplete_gamma_inv_deriv_1(const T value, const T a, const T lg_val) noexcept
Definition: incomplete_gamma_inv.hpp:134
constexpr T incomplete_gamma_inv_initial_val(const T a, const T p) noexcept
Definition: incomplete_gamma_inv.hpp:106
constexpr T incomplete_gamma_inv_ratio_val_2(const T value, const T a, const T deriv_1) noexcept
Definition: incomplete_gamma_inv.hpp:161
constexpr T incomplete_gamma_inv_check(const T a, const T p) noexcept
Definition: incomplete_gamma_inv.hpp:217
constexpr T incomplete_gamma_inv_initial_val_1_int_end(const T value_inp, const T a) noexcept
Definition: incomplete_gamma_inv.hpp:73
constexpr T incomplete_gamma_inv_initial_val_2(const T a, const T p, const T t_val) noexcept
Definition: incomplete_gamma_inv.hpp:91
constexpr T incomplete_gamma_inv_ratio_val_1(const T value, const T a, const T p, const T deriv_1) noexcept
Definition: incomplete_gamma_inv.hpp:152
constexpr T incomplete_gamma_inv_decision(const T value, const T a, const T p, const T direc, const T lg_val, const int iter_count) noexcept
Definition: incomplete_gamma_inv.hpp:191
constexpr bool any_nan(const T1 x, const T2 y) noexcept
Definition: is_nan.hpp:48
constexpr T incomplete_gamma_inv_halley(const T ratio_val_1, const T ratio_val_2) noexcept
Definition: incomplete_gamma_inv.hpp:170
constexpr T incomplete_gamma_inv_initial_val_1_int_begin(const T t_val) noexcept
Definition: incomplete_gamma_inv.hpp:63
constexpr TC incomplete_gamma_inv_type_check(const T1 a, const T2 p) noexcept
Definition: incomplete_gamma_inv.hpp:240
constexpr T incomplete_gamma_inv_deriv_2(const T value, const T a, const T deriv_1) noexcept
Definition: incomplete_gamma_inv.hpp:143
constexpr T incomplete_gamma_inv_begin(const T initial_val, const T a, const T p, const T lg_val) noexcept
Definition: incomplete_gamma_inv.hpp:207
constexpr T incomplete_gamma_inv_recur(const T value, const T a, const T p, const T deriv_1, const T lg_val, const int iter_count) noexcept
Definition: incomplete_gamma_inv.hpp:179
constexpr T incomplete_gamma_inv_err_val(const T value, const T a, const T p) noexcept
Definition: incomplete_gamma_inv.hpp:125
constexpr T incomplete_gamma_inv_initial_val_1(const T a, const T t_val, const T sgn_term) noexcept
Definition: incomplete_gamma_inv.hpp:82
constexpr T incomplete_gamma_inv_t_val_1(const T p) noexcept
Definition: incomplete_gamma_inv.hpp:43
Definition: is_even.hpp:29
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition: abs.hpp:40
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
constexpr common_t< T1, T2 > pow(const T1 base, const T2 exp_term) noexcept
Compile-time power function.
Definition: pow.hpp:82
constexpr common_t< T1, T2 > min(const T1 x, const T2 y) noexcept
Compile-time pairwise minimum function.
Definition: min.hpp:41
constexpr common_return_t< T1, T2 > incomplete_gamma_inv(const T1 a, const T2 p) noexcept
Compile-time inverse incomplete gamma function.
Definition: incomplete_gamma_inv.hpp:268
std::numeric_limits< T > GCLIM
Definition: gcem_options.hpp:74