@@ -26,35 +26,17 @@ auto apply_lcdfs_elem_impl(
26
26
);
27
27
}
28
28
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
-
50
29
template <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
+ });
58
40
}
59
41
}
60
42
@@ -84,9 +66,8 @@ auto apply_lcdfs(Ty&& y, Ttuple&& lcdf_tuple){
84
66
* @tparam T_lcdf_fun_tuple Type of tuple of LCDF functor tuples.
85
67
* @tparam T_chol Type of cholesky factor.
86
68
*/
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 (
90
71
const T_y& y, const T_lcdf_fun_tuple& lcdf_fun_tuple, const T_chol chol) {
91
72
static constexpr const char * function = " gaussian_copula_cholesky_lpdf" ;
92
73
@@ -97,15 +78,17 @@ T_return gaussian_copula_cholesky_lpdf(
97
78
check_consistent_sizes_mvt (function, " y" , y, " lcdf_fun_tuple" , lcdf_fun_tuple);
98
79
const size_t size_mvt_y = size_mvt (y);
99
80
const size_t size_mvt_lcdf_tuple = size_mvt (lcdf_fun_tuple);
100
- if (size_mvt_y == 0 ) {
101
- return 0 ;
102
- }
103
81
T_y_ref y_ref = y;
104
82
T_chol_ref chol_ref = chol;
105
83
T_lcdf_ref lcdf_tuple_ref = lcdf_fun_tuple;
106
84
107
85
vector_seq_view<T_y_ref> y_vec (y_ref);
108
86
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
+ }
109
92
const size_t size_vec = max_size_mvt (y, lcdf_fun_tuple);
110
93
111
94
const int size_y = math::size (y_vec[0 ]);
@@ -148,19 +131,29 @@ T_return gaussian_copula_cholesky_lpdf(
148
131
promote_scalar_t <T_return, std::vector<Eigen::VectorXd>> q (size_vec);
149
132
T_return lp (0 );
150
133
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
+ });
152
146
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);
154
148
lp -= std_normal_lpdf<propto>(q[i]);
155
149
}
156
150
const std::vector<Eigen::VectorXd> zero_vec (size_vec, rep_vector (0 , size_y));
157
151
lp += multi_normal_cholesky_lpdf<propto>(q, zero_vec, chol_ref);
158
152
return lp;
159
153
}
160
154
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 (
164
157
const T_y& y, const T_lcdf_fun_tuple& lcdf_fun_tuple, const T_chol chol) {
165
158
return gaussian_copula_cholesky_lpdf<false >(y, lcdf_fun_tuple, chol);
166
159
}
0 commit comments