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