@@ -26,35 +26,17 @@ auto apply_lcdfs_elem_impl(
2626 );
2727}
2828
29-
30- template <typename Ty, typename Ttuple, std::size_t ... I>
31- std::vector<return_type_t <Ty, Ttuple>> apply_lcdfs_impl (
32- Ty&& y, Ttuple&& lcdf_tuple, std::index_sequence<I...>) {
33- // Use initializer-list expansion to return a vector with the result of
34- // applying each LCDF functor to the respective input.
35- // We cannot use apply_scalar_unary here as we need a constant
36- // expression for indexing the tuple of LCDF functors
37- return {
38- apply_lcdfs_elem_impl (
39- std::forward<decltype (y[I])>(y[I]),
40- std::get<I>(lcdf_tuple),
41- std::make_index_sequence<
42- // Using size - 1 as the first element is the functor to apply
43- std::tuple_size<
44- std::remove_reference_t <
45- decltype (std::get<I>(lcdf_tuple))>>{} - 1 >{}
46- )...
47- };
48- }
49-
5029template <typename Ty, typename Ttuple>
51- auto apply_lcdfs (Ty&& y, Ttuple&& lcdf_tuple){
52- return apply_lcdfs_impl (
53- std::forward<Ty>(y),
54- std::forward<Ttuple>(lcdf_tuple),
55- std::make_index_sequence<
56- std::tuple_size<std::remove_reference_t <Ttuple>>{}>{}
57- );
30+ auto apply_lcdfs (Ty&& y, Ttuple&& lcdf_tuple) {
31+ return index_apply<std::tuple_size<std::remove_reference_t <Ttuple>>{}>(
32+ [&y, &lcdf_tuple](auto ... Is) {
33+ return std::make_tuple (
34+ apply_lcdfs_elem_impl (
35+ y[Is], std::get<Is>(lcdf_tuple), std::make_index_sequence<
36+ std::tuple_size<std::remove_reference_t <decltype (std::get<Is>(lcdf_tuple))>>{} - 1 >{}
37+ )...
38+ );
39+ });
5840}
5941}
6042
@@ -84,9 +66,8 @@ auto apply_lcdfs(Ty&& y, Ttuple&& lcdf_tuple){
8466 * @tparam T_lcdf_fun_tuple Type of tuple of LCDF functor tuples.
8567 * @tparam T_chol Type of cholesky factor.
8668 */
87- template <bool propto, typename T_y, typename T_lcdf_fun_tuple, typename T_chol,
88- typename T_return = return_type_t <T_y, T_lcdf_fun_tuple, T_chol>>
89- T_return gaussian_copula_cholesky_lpdf(
69+ template <bool propto, typename T_y, typename T_lcdf_fun_tuple, typename T_chol>
70+ auto gaussian_copula_cholesky_lpdf (
9071 const T_y& y, const T_lcdf_fun_tuple& lcdf_fun_tuple, const T_chol chol) {
9172 static constexpr const char * function = " gaussian_copula_cholesky_lpdf" ;
9273
@@ -97,15 +78,17 @@ T_return gaussian_copula_cholesky_lpdf(
9778 check_consistent_sizes_mvt (function, " y" , y, " lcdf_fun_tuple" , lcdf_fun_tuple);
9879 const size_t size_mvt_y = size_mvt (y);
9980 const size_t size_mvt_lcdf_tuple = size_mvt (lcdf_fun_tuple);
100- if (size_mvt_y == 0 ) {
101- return 0 ;
102- }
10381 T_y_ref y_ref = y;
10482 T_chol_ref chol_ref = chol;
10583 T_lcdf_ref lcdf_tuple_ref = lcdf_fun_tuple;
10684
10785 vector_seq_view<T_y_ref> y_vec (y_ref);
10886 vector_seq_view<T_lcdf_ref> lcdf_tuple_vec (lcdf_tuple_ref);
87+ using T_return = return_type_t <T_y, decltype (internal::apply_lcdfs (y_vec[0 ], lcdf_tuple_vec[0 ])), T_chol>;
88+
89+ if (size_mvt_y == 0 ) {
90+ return T_return (0 );
91+ }
10992 const size_t size_vec = max_size_mvt (y, lcdf_fun_tuple);
11093
11194 const int size_y = math::size (y_vec[0 ]);
@@ -148,19 +131,29 @@ T_return gaussian_copula_cholesky_lpdf(
148131 promote_scalar_t <T_return, std::vector<Eigen::VectorXd>> q (size_vec);
149132 T_return lp (0 );
150133 for (size_t i = 0 ; i < size_vec; i++) {
151- const auto & u = internal::apply_lcdfs (y_vec[i], lcdf_tuple_vec[i]);
134+ const auto & y_i = y_vec[i];
135+ const auto & func_i = lcdf_tuple_vec[i];
136+
137+ const auto & res = internal::apply_lcdfs (y_i, func_i);
138+ const auto & u = index_apply<std::tuple_size<std::remove_reference_t <decltype (res)>>{}>(
139+ [&res, size_y](auto ... Is) {
140+ Eigen::Matrix<T_return, Eigen::Dynamic, 1 > u_inner (size_y);
141+ static_cast <void >(std::initializer_list<int >{
142+ (u_inner[Is] = std::get<Is>(res), 0 )...
143+ });
144+ return u_inner;
145+ });
152146 check_bounded (function, " LCDF-transformed inputs" , u, NEGATIVE_INFTY, 0 );
153- q[i] = to_vector ( std_normal_log_qf (u) );
147+ q[i] = std_normal_log_qf (u);
154148 lp -= std_normal_lpdf<propto>(q[i]);
155149 }
156150 const std::vector<Eigen::VectorXd> zero_vec (size_vec, rep_vector (0 , size_y));
157151 lp += multi_normal_cholesky_lpdf<propto>(q, zero_vec, chol_ref);
158152 return lp;
159153}
160154
161- template <typename T_y, typename T_lcdf_fun_tuple, typename T_chol,
162- typename T_return = return_type_t <T_y, T_lcdf_fun_tuple, T_chol>>
163- T_return gaussian_copula_cholesky_lpdf(
155+ template <typename T_y, typename T_lcdf_fun_tuple, typename T_chol>
156+ auto gaussian_copula_cholesky_lpdf (
164157 const T_y& y, const T_lcdf_fun_tuple& lcdf_fun_tuple, const T_chol chol) {
165158 return gaussian_copula_cholesky_lpdf<false >(y, lcdf_fun_tuple, chol);
166159}
0 commit comments