WPILibC++ 2024.3.2
incomplete_beta_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 beta function
23 */
24
25#ifndef _gcem_incomplete_beta_inv_HPP
26#define _gcem_incomplete_beta_inv_HPP
27
28namespace gcem
29{
30
31namespace internal
32{
33
34template<typename T>
35constexpr T incomplete_beta_inv_decision(const T value, const T alpha_par, const T beta_par, const T p,
36 const T direc, const T lb_val, const int iter_count) noexcept;
37
38//
39// initial value for Halley
40
41//
42// a,b > 1 case
43
44template<typename T>
45constexpr
46T
48noexcept
49{ // a > 1.0
50 return( p > T(0.5) ? \
51 // if
52 sqrt(-T(2)*log(T(1) - p)) :
53 // else
54 sqrt(-T(2)*log(p)) );
55}
56
57template<typename T>
58constexpr
59T
61noexcept
62{ // internal for a > 1.0
63 return( t_val - ( T(2.515517) + T(0.802853)*t_val + T(0.010328)*t_val*t_val ) \
64 / ( T(1) + T(1.432788)*t_val + T(0.189269)*t_val*t_val + T(0.001308)*t_val*t_val*t_val ) );
65}
66
67template<typename T>
68constexpr
69T
70incomplete_beta_inv_initial_val_1_int_ab1(const T alpha_par, const T beta_par)
71noexcept
72{
73 return( T(1)/(2*alpha_par - T(1)) + T(1)/(2*beta_par - T(1)) );
74}
75
76template<typename T>
77constexpr
78T
79incomplete_beta_inv_initial_val_1_int_ab2(const T alpha_par, const T beta_par)
80noexcept
81{
82 return( T(1)/(2*beta_par - T(1)) - T(1)/(2*alpha_par - T(1)) );
83}
84
85template<typename T>
86constexpr
87T
89noexcept
90{
91 return( T(2) / ab_term_1 );
92}
93
94template<typename T>
95constexpr
96T
97incomplete_beta_inv_initial_val_1_int_w(const T value, const T ab_term_2, const T h_term)
98noexcept
99{
100 // return( value * sqrt(h_term + lambda)/h_term - ab_term_2*(lambda + 5.0/6.0 -2.0/(3.0*h_term)) );
101 return( value * sqrt(h_term + (value*value - T(3))/T(6))/h_term \
102 - ab_term_2*((value*value - T(3))/T(6) + T(5)/T(6) - T(2)/(T(3)*h_term)) );
103}
104
105template<typename T>
106constexpr
107T
108incomplete_beta_inv_initial_val_1_int_end(const T alpha_par, const T beta_par, const T w_term)
109noexcept
110{
111 return( alpha_par / (alpha_par + beta_par*exp(2*w_term)) );
112}
113
114template<typename T>
115constexpr
116T
117incomplete_beta_inv_initial_val_1(const T alpha_par, const T beta_par, const T t_val, const T sgn_term)
118noexcept
119{ // a > 1.0
120 return incomplete_beta_inv_initial_val_1_int_end( alpha_par, beta_par,
126 )
127 )
128 );
129}
130
131//
132// a,b else
133
134template<typename T>
135constexpr
136T
137incomplete_beta_inv_initial_val_2_s1(const T alpha_par, const T beta_par)
138noexcept
139{
140 return( pow(alpha_par/(alpha_par+beta_par),alpha_par) / alpha_par );
141}
142
143template<typename T>
144constexpr
145T
146incomplete_beta_inv_initial_val_2_s2(const T alpha_par, const T beta_par)
147noexcept
148{
149 return( pow(beta_par/(alpha_par+beta_par),beta_par) / beta_par );
150}
151
152template<typename T>
153constexpr
154T
155incomplete_beta_inv_initial_val_2(const T alpha_par, const T beta_par, const T p, const T s_1, const T s_2)
156noexcept
157{
158 return( p <= s_1/(s_1 + s_2) ? pow(p*(s_1+s_2)*alpha_par,T(1)/alpha_par) :
159 T(1) - pow(p*(s_1+s_2)*beta_par,T(1)/beta_par) );
160}
161
162// initial value
163
164template<typename T>
165constexpr
166T
167incomplete_beta_inv_initial_val(const T alpha_par, const T beta_par, const T p)
168noexcept
169{
170 return( (alpha_par > T(1) && beta_par > T(1)) ?
171 // if
172 incomplete_beta_inv_initial_val_1(alpha_par,beta_par,
174 p < T(0.5) ? T(1) : T(-1) ) :
175 // else
176 p > T(0.5) ?
177 // if
178 T(1) - incomplete_beta_inv_initial_val_2(beta_par,alpha_par,T(1) - p,
179 incomplete_beta_inv_initial_val_2_s1(beta_par,alpha_par),
180 incomplete_beta_inv_initial_val_2_s2(beta_par,alpha_par)) :
181 // else
182 incomplete_beta_inv_initial_val_2(alpha_par,beta_par,p,
183 incomplete_beta_inv_initial_val_2_s1(alpha_par,beta_par),
184 incomplete_beta_inv_initial_val_2_s2(alpha_par,beta_par))
185 );
186}
187
188//
189// Halley recursion
190
191template<typename T>
192constexpr
193T
194incomplete_beta_inv_err_val(const T value, const T alpha_par, const T beta_par, const T p)
195noexcept
196{ // err_val = f(x)
197 return( incomplete_beta(alpha_par,beta_par,value) - p );
198}
199
200template<typename T>
201constexpr
202T
203incomplete_beta_inv_deriv_1(const T value, const T alpha_par, const T beta_par, const T lb_val)
204noexcept
205{ // derivative of the incomplete beta function w.r.t. x
206 return( // indistinguishable from zero or one
207 GCLIM<T>::min() > abs(value) ? \
208 T(0) :
209 GCLIM<T>::min() > abs(T(1) - value) ? \
210 T(0) :
211 // else
212 exp( (alpha_par - T(1))*log(value) + (beta_par - T(1))*log(T(1) - value) - lb_val ) );
213}
214
215template<typename T>
216constexpr
217T
218incomplete_beta_inv_deriv_2(const T value, const T alpha_par, const T beta_par, const T deriv_1)
219noexcept
220{ // second derivative of the incomplete beta function w.r.t. x
221 return( deriv_1*((alpha_par - T(1))/value - (beta_par - T(1))/(T(1) - value)) );
222}
223
224template<typename T>
225constexpr
226T
227incomplete_beta_inv_ratio_val_1(const T value, const T alpha_par, const T beta_par, const T p, const T deriv_1)
228noexcept
229{
230 return( incomplete_beta_inv_err_val(value,alpha_par,beta_par,p) / deriv_1 );
231}
232
233template<typename T>
234constexpr
235T
236incomplete_beta_inv_ratio_val_2(const T value, const T alpha_par, const T beta_par, const T deriv_1)
237noexcept
238{
239 return( incomplete_beta_inv_deriv_2(value,alpha_par,beta_par,deriv_1) / deriv_1 );
240}
241
242template<typename T>
243constexpr
244T
245incomplete_beta_inv_halley(const T ratio_val_1, const T ratio_val_2)
246noexcept
247{
248 return( ratio_val_1 / max( T(0.8), min( T(1.2), T(1) - T(0.5)*ratio_val_1*ratio_val_2 ) ) );
249}
250
251template<typename T>
252constexpr
253T
254incomplete_beta_inv_recur(const T value, const T alpha_par, const T beta_par, const T p, const T deriv_1,
255 const T lb_val, const int iter_count)
256noexcept
257{
258 return( // derivative = 0
259 GCLIM<T>::min() > abs(deriv_1) ? \
260 incomplete_beta_inv_decision( value, alpha_par, beta_par, p, T(0), lb_val,
262 // else
263 incomplete_beta_inv_decision( value, alpha_par, beta_par, p,
265 incomplete_beta_inv_ratio_val_1(value,alpha_par,beta_par,p,deriv_1),
266 incomplete_beta_inv_ratio_val_2(value,alpha_par,beta_par,deriv_1)
267 ), lb_val, iter_count) );
268}
269
270template<typename T>
271constexpr
272T
273incomplete_beta_inv_decision(const T value, const T alpha_par, const T beta_par, const T p, const T direc,
274 const T lb_val, const int iter_count)
275noexcept
276{
277 return( iter_count <= GCEM_INCML_BETA_INV_MAX_ITER ?
278 // if
279 incomplete_beta_inv_recur(value-direc,alpha_par,beta_par,p,
280 incomplete_beta_inv_deriv_1(value,alpha_par,beta_par,lb_val),
281 lb_val, iter_count+1) :
282 // else
283 value - direc );
284}
285
286template<typename T>
287constexpr
288T
289incomplete_beta_inv_begin(const T initial_val, const T alpha_par, const T beta_par, const T p, const T lb_val)
290noexcept
291{
292 return incomplete_beta_inv_recur(initial_val,alpha_par,beta_par,p,
293 incomplete_beta_inv_deriv_1(initial_val,alpha_par,beta_par,lb_val),
294 lb_val,1);
295}
296
297template<typename T>
298constexpr
299T
300incomplete_beta_inv_check(const T alpha_par, const T beta_par, const T p)
301noexcept
302{
303 return( // NaN check
304 any_nan(alpha_par, beta_par, p) ? \
306 // indistinguishable from zero or one
307 GCLIM<T>::min() > p ? \
308 T(0) :
309 GCLIM<T>::min() > abs(T(1) - p) ? \
310 T(1) :
311 // else
313 alpha_par,beta_par,p,lbeta(alpha_par,beta_par)) );
314}
315
316template<typename T1, typename T2, typename T3, typename TC = common_t<T1,T2,T3>>
317constexpr
318TC
319incomplete_beta_inv_type_check(const T1 a, const T2 b, const T3 p)
320noexcept
321{
322 return incomplete_beta_inv_check(static_cast<TC>(a),
323 static_cast<TC>(b),
324 static_cast<TC>(p));
325}
326
327}
328
329/**
330 * Compile-time inverse incomplete beta function
331 *
332 * @param a a real-valued, non-negative input.
333 * @param b a real-valued, non-negative input.
334 * @param p a real-valued input with values in the unit-interval.
335 *
336 * @return Computes the inverse incomplete beta function, a value \f$ x \f$ such that
337 * \f[ f(x) := \frac{\text{B}(x;\alpha,\beta)}{\text{B}(\alpha,\beta)} - p \f]
338 * equal to zero, for a given \c p.
339 * GCE-Math finds this root using Halley's method:
340 * \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]
341 * where
342 * \f[ \frac{\partial}{\partial x} \left(\frac{\text{B}(x;\alpha,\beta)}{\text{B}(\alpha,\beta)}\right) = \frac{1}{\text{B}(\alpha,\beta)} x^{\alpha-1} (1-x)^{\beta-1} \f]
343 * \f[ \frac{\partial^2}{\partial x^2} \left(\frac{\text{B}(x;\alpha,\beta)}{\text{B}(\alpha,\beta)}\right) = \frac{1}{\text{B}(\alpha,\beta)} x^{\alpha-1} (1-x)^{\beta-1} \left( \frac{\alpha-1}{x} - \frac{\beta-1}{1 - x} \right) \f]
344 */
345
346template<typename T1, typename T2, typename T3>
347constexpr
348common_t<T1,T2,T3>
349incomplete_beta_inv(const T1 a, const T2 b, const T3 p)
350noexcept
351{
353}
354
355}
356
357#endif
#define GCEM_INCML_BETA_INV_MAX_ITER
Definition: gcem_options.hpp:169
constexpr T incomplete_beta_inv_begin(const T initial_val, const T alpha_par, const T beta_par, const T p, const T lb_val) noexcept
Definition: incomplete_beta_inv.hpp:289
constexpr T incomplete_beta_inv_initial_val_1_int_w(const T value, const T ab_term_2, const T h_term) noexcept
Definition: incomplete_beta_inv.hpp:97
constexpr T incomplete_beta_inv_initial_val_1_int_ab1(const T alpha_par, const T beta_par) noexcept
Definition: incomplete_beta_inv.hpp:70
constexpr T incomplete_beta_inv_recur(const T value, const T alpha_par, const T beta_par, const T p, const T deriv_1, const T lb_val, const int iter_count) noexcept
Definition: incomplete_beta_inv.hpp:254
constexpr T incomplete_beta_inv_check(const T alpha_par, const T beta_par, const T p) noexcept
Definition: incomplete_beta_inv.hpp:300
constexpr TC incomplete_beta_inv_type_check(const T1 a, const T2 b, const T3 p) noexcept
Definition: incomplete_beta_inv.hpp:319
constexpr T incomplete_beta_inv_initial_val_2_s1(const T alpha_par, const T beta_par) noexcept
Definition: incomplete_beta_inv.hpp:137
constexpr T incomplete_beta_inv_ratio_val_1(const T value, const T alpha_par, const T beta_par, const T p, const T deriv_1) noexcept
Definition: incomplete_beta_inv.hpp:227
constexpr T incomplete_beta_inv_initial_val_1_int_h(const T ab_term_1) noexcept
Definition: incomplete_beta_inv.hpp:88
constexpr T incomplete_beta_inv_initial_val_1_int_ab2(const T alpha_par, const T beta_par) noexcept
Definition: incomplete_beta_inv.hpp:79
constexpr T incomplete_beta_inv_ratio_val_2(const T value, const T alpha_par, const T beta_par, const T deriv_1) noexcept
Definition: incomplete_beta_inv.hpp:236
constexpr bool any_nan(const T1 x, const T2 y) noexcept
Definition: is_nan.hpp:48
constexpr T incomplete_beta_inv_initial_val_2_s2(const T alpha_par, const T beta_par) noexcept
Definition: incomplete_beta_inv.hpp:146
constexpr T incomplete_beta_inv_deriv_2(const T value, const T alpha_par, const T beta_par, const T deriv_1) noexcept
Definition: incomplete_beta_inv.hpp:218
constexpr T incomplete_beta_inv_err_val(const T value, const T alpha_par, const T beta_par, const T p) noexcept
Definition: incomplete_beta_inv.hpp:194
constexpr T incomplete_beta_inv_initial_val_1_tval(const T p) noexcept
Definition: incomplete_beta_inv.hpp:47
constexpr T incomplete_beta_inv_decision(const T value, const T alpha_par, const T beta_par, const T p, const T direc, const T lb_val, const int iter_count) noexcept
Definition: incomplete_beta_inv.hpp:273
constexpr T incomplete_beta_inv_initial_val_1_int_end(const T alpha_par, const T beta_par, const T w_term) noexcept
Definition: incomplete_beta_inv.hpp:108
constexpr T incomplete_beta_inv_deriv_1(const T value, const T alpha_par, const T beta_par, const T lb_val) noexcept
Definition: incomplete_beta_inv.hpp:203
constexpr T incomplete_beta_inv_initial_val_2(const T alpha_par, const T beta_par, const T p, const T s_1, const T s_2) noexcept
Definition: incomplete_beta_inv.hpp:155
constexpr T incomplete_beta_inv_initial_val_1(const T alpha_par, const T beta_par, const T t_val, const T sgn_term) noexcept
Definition: incomplete_beta_inv.hpp:117
constexpr T incomplete_beta_inv_halley(const T ratio_val_1, const T ratio_val_2) noexcept
Definition: incomplete_beta_inv.hpp:245
constexpr T incomplete_beta_inv_initial_val_1_int_begin(const T t_val) noexcept
Definition: incomplete_beta_inv.hpp:60
constexpr T incomplete_beta_inv_initial_val(const T alpha_par, const T beta_par, const T p) noexcept
Definition: incomplete_beta_inv.hpp:167
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, T3 > incomplete_beta_inv(const T1 a, const T2 b, const T3 p) noexcept
Compile-time inverse incomplete beta function.
Definition: incomplete_beta_inv.hpp:349
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, 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
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
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