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