@@ -43,12 +43,6 @@ template <typename T_n, typename T_r, typename T_alpha, typename T_beta>
4343inline return_type_t <T_r, T_alpha, T_beta> beta_neg_binomial_lccdf (
4444 const T_n& n, const T_r& r, const T_alpha& alpha, const T_beta& beta,
4545 const double precision = 1e-8 , const int max_steps = 1e6 ) {
46- using std::exp;
47- using std::log;
48- using T_partials_return = partials_return_t <T_n, T_r, T_alpha, T_beta>;
49- using T_r_ref = ref_type_t <T_r>;
50- using T_alpha_ref = ref_type_t <T_alpha>;
51- using T_beta_ref = ref_type_t <T_beta>;
5246 static constexpr const char * function = " beta_neg_binomial_lccdf" ;
5347 check_consistent_sizes (
5448 function, " Failures variable" , n, " Number of successes parameter" , r,
@@ -57,67 +51,70 @@ inline return_type_t<T_r, T_alpha, T_beta> beta_neg_binomial_lccdf(
5751 return 0 ;
5852 }
5953
54+ using T_r_ref = ref_type_t <T_r>;
6055 T_r_ref r_ref = r;
56+ using T_alpha_ref = ref_type_t <T_alpha>;
6157 T_alpha_ref alpha_ref = alpha;
58+ using T_beta_ref = ref_type_t <T_beta>;
6259 T_beta_ref beta_ref = beta;
6360 check_positive_finite (function, " Number of successes parameter" , r_ref);
6461 check_positive_finite (function, " Prior success parameter" , alpha_ref);
6562 check_positive_finite (function, " Prior failure parameter" , beta_ref);
6663
67- T_partials_return log_ccdf (0.0 );
68- auto ops_partials = make_partials_propagator (r_ref, alpha_ref, beta_ref);
6964
7065 scalar_seq_view<T_n> n_vec (n);
7166 scalar_seq_view<T_r_ref> r_vec (r_ref);
7267 scalar_seq_view<T_alpha_ref> alpha_vec (alpha_ref);
7368 scalar_seq_view<T_beta_ref> beta_vec (beta_ref);
74- size_t size_n = stan::math::size (n);
69+ int size_n = stan::math::size (n);
7570 size_t max_size_seq_view = max_size (n, r, alpha, beta);
7671
7772 // Explicit return for extreme values
7873 // The gradients are technically ill-defined, but treated as zero
79- for (size_t i = 0 ; i < size_n; i++) {
74+ for (int i = 0 ; i < size_n; i++) {
8075 if (n_vec.val (i) < 0 ) {
81- return ops_partials. build ( 0.0 ) ;
76+ return 0.0 ;
8277 }
8378 }
8479
80+ using T_partials_return = partials_return_t <T_n, T_r, T_alpha, T_beta>;
81+ T_partials_return log_ccdf (0.0 );
82+ auto ops_partials = make_partials_propagator (r_ref, alpha_ref, beta_ref);
8583 for (size_t i = 0 ; i < max_size_seq_view; i++) {
8684 // Explicit return for extreme values
8785 // The gradients are technically ill-defined, but treated as zero
8886 if (n_vec.val (i) == std::numeric_limits<int >::max ()) {
8987 return ops_partials.build (negative_infinity ());
9088 }
91- T_partials_return n_dbl = n_vec.val (i);
92- T_partials_return r_dbl = r_vec.val (i);
93- T_partials_return alpha_dbl = alpha_vec.val (i);
94- T_partials_return beta_dbl = beta_vec.val (i);
95- T_partials_return b_plus_n = beta_dbl + n_dbl;
96- T_partials_return r_plus_n = r_dbl + n_dbl;
97- T_partials_return a_plus_r = alpha_dbl + r_dbl;
98- T_partials_return one = 1 ;
99- T_partials_return precision_t
100- = precision; // default -6, set -8 to pass all tests
101-
102- T_partials_return F
103- = hypergeometric_3F2 ({one, b_plus_n + 1 , r_plus_n + 1 },
104- {n_dbl + 2 , a_plus_r + b_plus_n + 1 }, one);
105- T_partials_return C = lgamma (r_plus_n + 1 ) + lbeta (a_plus_r, b_plus_n + 1 )
89+ auto n_dbl = n_vec.val (i);
90+ auto r_dbl = r_vec.val (i);
91+ auto alpha_dbl = alpha_vec.val (i);
92+ auto beta_dbl = beta_vec.val (i);
93+ auto b_plus_n = beta_dbl + n_dbl;
94+ auto r_plus_n = r_dbl + n_dbl;
95+ auto a_plus_r = alpha_dbl + r_dbl;
96+ using a_t = return_type_t <decltype (b_plus_n), decltype (r_plus_n)>;
97+ using b_t = return_type_t <decltype (n_dbl), decltype (a_plus_r), decltype (b_plus_n)>;
98+ auto F
99+ = hypergeometric_3F2 (
100+ std::initializer_list<a_t >{1.0 , b_plus_n + 1.0 , r_plus_n + 1.0 },
101+ std::initializer_list<b_t >{n_dbl + 2.0 , a_plus_r + b_plus_n + 1.0 }, 1.0 );
102+ auto C = lgamma (r_plus_n + 1.0 ) + lbeta (a_plus_r, b_plus_n + 1.0 )
106103 - lgamma (r_dbl) - lbeta (alpha_dbl, beta_dbl)
107104 - lgamma (n_dbl + 2 );
108- T_partials_return ccdf = exp (C) * F;
109- T_partials_return log_ccdf_i = log (ccdf);
110- log_ccdf += log_ccdf_i;
105+ log_ccdf += C + stan::math::log (F);
111106
112107 if constexpr (!is_constant_all<T_r, T_alpha, T_beta>::value) {
113- T_partials_return digamma_n_r_alpha_beta
114- = digamma (a_plus_r + b_plus_n + 1 );
108+ auto digamma_n_r_alpha_beta
109+ = digamma (a_plus_r + b_plus_n + 1.0 );
115110 T_partials_return dF[6 ];
116- grad_F32 (dF, one, b_plus_n + 1 , r_plus_n + 1 , n_dbl + 2 ,
117- a_plus_r + b_plus_n + 1 , one, precision_t , max_steps);
111+ grad_F32<false , !is_constant<T_beta>::value,
112+ !is_constant_all<T_r>::value, false , true , false >(dF, 1.0 ,
113+ b_plus_n + 1.0 , r_plus_n + 1.0 , n_dbl + 2.0 ,
114+ a_plus_r + b_plus_n + 1.0 , 1.0 , precision, max_steps);
118115
119116 if constexpr (!is_constant<T_r>::value || !is_constant<T_alpha>::value) {
120- T_partials_return digamma_r_alpha = digamma (a_plus_r);
117+ auto digamma_r_alpha = digamma (a_plus_r);
121118 if constexpr (!is_constant_all<T_r>::value) {
122119 partials<0 >(ops_partials)[i]
123120 += digamma (r_plus_n + 1 )
@@ -133,7 +130,7 @@ inline return_type_t<T_r, T_alpha, T_beta> beta_neg_binomial_lccdf(
133130
134131 if constexpr (!is_constant<T_alpha>::value
135132 || !is_constant<T_beta>::value) {
136- T_partials_return digamma_alpha_beta = digamma (alpha_dbl + beta_dbl);
133+ auto digamma_alpha_beta = digamma (alpha_dbl + beta_dbl);
137134 if constexpr (!is_constant<T_alpha>::value) {
138135 partials<1 >(ops_partials)[i] += digamma_alpha_beta;
139136 }
0 commit comments