Automatic Differentiation
 
Loading...
Searching...
No Matches
student_t_qf.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_FWD_PROB_STUDENT_T_QF_HPP
2#define STAN_MATH_FWD_PROB_STUDENT_T_QF_HPP
3
16
17namespace stan {
18namespace math {
19
20template <typename T_p, typename T_nu, typename T_mu, typename T_sigma,
21 require_all_stan_scalar_t<T_p, T_mu, T_sigma, T_nu>* = nullptr,
22 require_any_fvar_t<T_p, T_nu, T_mu, T_sigma>* = nullptr>
23inline auto student_t_qf(const T_p& p, const T_nu& nu, const T_mu& mu,
24 const T_sigma& sigma) {
25 static constexpr const char* function = "student_t_qf";
27 using T_partials = partials_type_t<FvarT>;
28
29 auto p_val = value_of(p);
30 auto nu_val = value_of(nu);
31 auto mu_val = value_of(mu);
32 auto sigma_val = value_of(sigma);
33
34 check_nonnegative(function, "Degrees of freedom parameter", nu_val);
35 check_positive(function, "Scale parameter", sigma_val);
36 check_bounded(function, "Probability parameter", p_val, 0.0, 1.0);
37
38 if (unlikely(p_val == 0.0)) {
39 return FvarT{NEGATIVE_INFTY, 0.0};
40 } else if (unlikely(p_val == 1.0)) {
41 return FvarT{INFTY, 0.0};
42 } else if (unlikely(p_val == 0.5)) {
43 return FvarT{mu_val, 0.0};
44 }
45
46 const auto p_val_flip = p_val < 0.5 ? p_val : 1.0 - p_val;
47 const double p_sign = value_of_rec(p_val) < 0.5 ? -1.0 : 1.0;
48 auto sqrt_nu_val = sqrt(nu_val);
49 auto ibeta_arg = inv_inc_beta(0.5 * nu_val, 0.5, 2.0 * p_val_flip);
50 auto rtn_val
51 = mu_val
52 + p_sign * sigma_val * sqrt_nu_val * sqrt(-1.0 + 1.0 / ibeta_arg);
53
54 FvarT rtn(rtn_val, 0.0);
55
56 if constexpr (is_autodiff_v<T_p>) {
57 rtn.d_ += p.d_ * exp(-student_t_lpdf(rtn_val, nu_val, mu_val, sigma_val));
58 }
59
60 if constexpr (is_autodiff_v<T_nu>) {
61 const auto half_nu = nu_val / 2.0;
62 Eigen::Matrix<T_partials, -1, 1> hyper_arg_a{{0.5, half_nu, half_nu}};
63 Eigen::Matrix<T_partials, -1, 1> hyper_arg_b{
64 {1.0 + half_nu, 1.0 + half_nu}};
65 const auto hyper_arg
66 = hypergeometric_pFq(hyper_arg_a, hyper_arg_b, ibeta_arg);
67 const auto hyper2f1 = hypergeometric_2F1(1.0, (1.0 + nu_val) / 2.0,
68 (2.0 + nu_val) / 2.0, ibeta_arg);
69 const auto digamma_a1 = digamma(half_nu);
70 const auto digamma_a2 = digamma((1.0 + nu_val) / 2.0);
71
72 const auto arg_1 = (4.0 * hyper_arg * sqrt(1.0 - ibeta_arg)) / nu_val;
73 const auto arg_2 = -2.0 * hyper2f1 * (-1.0 + ibeta_arg)
74 * (log(ibeta_arg) - digamma_a1 + digamma_a2);
75
76 const auto num1 = sigma_val * (-2.0 + (2.0 - arg_1 + arg_2) / ibeta_arg);
77 const auto den1 = 4.0 * sqrt_nu_val * sqrt(-1.0 + 1.0 / ibeta_arg);
78 rtn.d_ += nu.d_ * p_sign * num1 / den1;
79 }
80
81 if constexpr (is_autodiff_v<T_mu>) {
82 rtn.d_ += mu.d_;
83 }
84
85 if constexpr (is_autodiff_v<T_sigma>) {
86 rtn.d_ += sigma.d_ * p_sign * sqrt_nu_val * sqrt(-1.0 + 1.0 / ibeta_arg);
87 }
88
89 return rtn;
90}
91} // namespace math
92} // namespace stan
93
94#endif
#define unlikely(x)
return_type_t< T_y_cl, T_dof_cl, T_loc_cl, T_scale_cl > student_t_lpdf(const T_y_cl &y, const T_dof_cl &nu, const T_loc_cl &mu, const T_scale_cl &sigma)
The log of the Student-t density for the given y, nu, mean, and scale parameter.
typename partials_type< T >::type partials_type_t
Helper alias for accessing the partial type.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
double value_of_rec(const fvar< T > &v)
Return the value of the specified variable.
void check_nonnegative(const char *function, const char *name, const T_y &y)
Check if y is non-negative.
void check_bounded(const char *function, const char *name, const T_y &y, const T_low &low, const T_high &high)
Check if the value is between the low and high values, inclusively.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
fvar< T > log(const fvar< T > &x)
Definition log.hpp:18
static constexpr double NEGATIVE_INFTY
Negative infinity.
Definition constants.hpp:51
fvar< T > sqrt(const fvar< T > &x)
Definition sqrt.hpp:18
auto student_t_qf(const T_p &p, const T_nu &nu, const T_mu &mu, const T_sigma &sigma)
fvar< partials_return_t< T1, T2, T3 > > inv_inc_beta(const T1 &a, const T2 &b, const T3 &p)
The inverse of the normalized incomplete beta function of a, b, with probability p.
FvarT hypergeometric_pFq(Ta &&a, Tb &&b, Tz &&z)
Returns the generalized hypergeometric (pFq) function applied to the input arguments.
void check_positive(const char *function, const char *name, const T_y &y)
Check if y is positive.
return_type_t< Ta1, Ta2, Tb, Tz > hypergeometric_2F1(const Ta1 &a1, const Ta2 &a2, const Tb &b, const Tz &z)
Returns the Gauss hypergeometric function applied to the input arguments: .
static constexpr double INFTY
Positive infinity.
Definition constants.hpp:46
fvar< T > digamma(const fvar< T > &x)
Return the derivative of the log gamma function at the specified argument.
Definition digamma.hpp:23
fvar< T > exp(const fvar< T > &x)
Definition exp.hpp:15
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...