Skip to content

Commit 6e340ec

Browse files
committed
Broaden the template bound on the lp argument to constraints
1 parent ac977e4 commit 6e340ec

17 files changed

Lines changed: 327 additions & 184 deletions

stan/math/prim/constraint/cholesky_corr_constrain.hpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ cholesky_corr_constrain(const EigVec& y, int K) {
4343
}
4444

4545
// FIXME to match above after debugged
46-
template <typename EigVec, require_eigen_vector_t<EigVec>* = nullptr>
46+
template <typename EigVec, typename Lp,
47+
require_eigen_vector_t<EigVec>* = nullptr,
48+
require_convertible_t<return_type_t<EigVec>, Lp>* = nullptr>
4749
inline Eigen::Matrix<value_type_t<EigVec>, Eigen::Dynamic, Eigen::Dynamic>
48-
cholesky_corr_constrain(const EigVec& y, int K, return_type_t<EigVec>& lp) {
50+
cholesky_corr_constrain(const EigVec& y, int K, Lp& lp) {
4951
using Eigen::Dynamic;
5052
using Eigen::Matrix;
5153
using std::sqrt;
@@ -85,13 +87,17 @@ cholesky_corr_constrain(const EigVec& y, int K, return_type_t<EigVec>& lp) {
8587
* @tparam T A type inheriting from `Eigen::DenseBase` or a `var_value` with
8688
* inner type inheriting from `Eigen::DenseBase` with compile time dynamic rows
8789
* and 1 column
90+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
91+
* convertable to this.
8892
* @param y Linearly Serialized vector of size `(K * (K - 1))/2` holding the
8993
* column major order elements of the lower triangurlar
9094
* @param K The size of the matrix to return
9195
* @param[in,out] lp log density accumulator
9296
*/
93-
template <bool Jacobian, typename T, require_not_std_vector_t<T>* = nullptr>
94-
inline auto cholesky_corr_constrain(const T& y, int K, return_type_t<T>& lp) {
97+
template <bool Jacobian, typename T, typename Lp,
98+
require_not_std_vector_t<T>* = nullptr,
99+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
100+
inline auto cholesky_corr_constrain(const T& y, int K, Lp& lp) {
95101
if (Jacobian) {
96102
return cholesky_corr_constrain(y, K, lp);
97103
} else {
@@ -110,13 +116,17 @@ inline auto cholesky_corr_constrain(const T& y, int K, return_type_t<T>& lp) {
110116
* @tparam T A standard vector with inner type inheriting from
111117
* `Eigen::DenseBase` or a `var_value` with inner type inheriting from
112118
* `Eigen::DenseBase` with compile time dynamic rows and 1 column
119+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
120+
* convertable to this.
113121
* @param y Linearly Serialized vector of size `(K * (K - 1))/2` holding the
114122
* column major order elements of the lower triangurlar
115123
* @param K The size of the matrix to return
116124
* @param[in,out] lp log density accumulator
117125
*/
118-
template <bool Jacobian, typename T, require_std_vector_t<T>* = nullptr>
119-
inline auto cholesky_corr_constrain(const T& y, int K, return_type_t<T>& lp) {
126+
template <bool Jacobian, typename T, typename Lp,
127+
require_std_vector_t<T>* = nullptr,
128+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
129+
inline auto cholesky_corr_constrain(const T& y, int K, Lp& lp) {
120130
return apply_vector_unary<T>::apply(y, [&lp, K](auto&& v) {
121131
return cholesky_corr_constrain<Jacobian>(v, K, lp);
122132
});

stan/math/prim/constraint/cholesky_factor_constrain.hpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ cholesky_factor_constrain(const T& x, int M, int N) {
7070
* determinant
7171
* @return Cholesky factor
7272
*/
73-
template <typename T, require_eigen_vector_t<T>* = nullptr>
73+
template <typename T, typename Lp, require_eigen_vector_t<T>* = nullptr,
74+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
7475
inline Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic>
75-
cholesky_factor_constrain(const T& x, int M, int N, return_type_t<T>& lp) {
76+
cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) {
7677
check_size_match("cholesky_factor_constrain", "x.size()", x.size(),
7778
"((N * (N + 1)) / 2 + (M - N) * N)",
7879
((N * (N + 1)) / 2 + (M - N) * N));
@@ -99,15 +100,18 @@ cholesky_factor_constrain(const T& x, int M, int N, return_type_t<T>& lp) {
99100
* @tparam T A type inheriting from `Eigen::DenseBase` or a `var_value` with
100101
* inner type inheriting from `Eigen::DenseBase` with compile time dynamic rows
101102
* and 1 column
103+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
104+
* convertable to this.
102105
* @param x Vector of unconstrained values
103106
* @param M number of rows
104107
* @param N number of columns
105108
* @param[in,out] lp log density accumulator
106109
* @return Cholesky factor
107110
*/
108-
template <bool Jacobian, typename T, require_not_std_vector_t<T>* = nullptr>
109-
inline auto cholesky_factor_constrain(const T& x, int M, int N,
110-
return_type_t<T>& lp) {
111+
template <bool Jacobian, typename T, typename Lp,
112+
require_not_std_vector_t<T>* = nullptr,
113+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
114+
inline auto cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) {
111115
if (Jacobian) {
112116
return cholesky_factor_constrain(x, M, N, lp);
113117
} else {
@@ -129,15 +133,18 @@ inline auto cholesky_factor_constrain(const T& x, int M, int N,
129133
* @tparam T A standard vector with inner type inheriting from
130134
* `Eigen::DenseBase` or a `var_value` with inner type inheriting from
131135
* `Eigen::DenseBase` with compile time dynamic rows and 1 column
136+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
137+
* convertable to this.
132138
* @param x Vector of unconstrained values
133139
* @param M number of rows
134140
* @param N number of columns
135141
* @param[in,out] lp log density accumulator
136142
* @return Cholesky factor
137143
*/
138-
template <bool Jacobian, typename T, require_std_vector_t<T>* = nullptr>
139-
inline auto cholesky_factor_constrain(const T& x, int M, int N,
140-
return_type_t<T>& lp) {
144+
template <bool Jacobian, typename T, typename Lp,
145+
require_std_vector_t<T>* = nullptr,
146+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
147+
inline auto cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) {
141148
return apply_vector_unary<T>::apply(x, [&lp, M, N](auto&& v) {
142149
return cholesky_factor_constrain<Jacobian>(v, M, N, lp);
143150
});

stan/math/prim/constraint/corr_matrix_constrain.hpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,16 @@ corr_matrix_constrain(const T& x, Eigen::Index k) {
6161
*
6262
* @tparam T type of the vector (must be derived from \c Eigen::MatrixBase and
6363
* have one compile-time dimension equal to 1)
64+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
65+
* convertable to this.
6466
* @param x Vector of unconstrained partial correlations.
6567
* @param k Dimensionality of returned correlation matrix.
6668
* @param lp Log probability reference to increment.
6769
*/
68-
template <typename T, require_eigen_col_vector_t<T>* = nullptr>
70+
template <typename T, typename Lp, require_eigen_col_vector_t<T>* = nullptr,
71+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
6972
inline Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic>
70-
corr_matrix_constrain(const T& x, Eigen::Index k, return_type_t<T>& lp) {
73+
corr_matrix_constrain(const T& x, Eigen::Index k, Lp& lp) {
7174
Eigen::Index k_choose_2 = (k * (k - 1)) / 2;
7275
check_size_match("cov_matrix_constrain", "x.size()", x.size(), "k_choose_2",
7376
k_choose_2);
@@ -89,13 +92,16 @@ corr_matrix_constrain(const T& x, Eigen::Index k, return_type_t<T>& lp) {
8992
* @tparam T A type inheriting from `Eigen::DenseBase` or a `var_value` with
9093
* inner type inheriting from `Eigen::DenseBase` with compile time dynamic rows
9194
* and 1 column
95+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
96+
* convertable to this.
9297
* @param x Vector of unconstrained partial correlations
9398
* @param k Dimensionality of returned correlation matrix
9499
* @param[in,out] lp log density accumulator
95100
*/
96-
template <bool Jacobian, typename T, require_not_std_vector_t<T>* = nullptr>
97-
inline auto corr_matrix_constrain(const T& x, Eigen::Index k,
98-
return_type_t<T>& lp) {
101+
template <bool Jacobian, typename T, typename Lp,
102+
require_not_std_vector_t<T>* = nullptr,
103+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
104+
inline auto corr_matrix_constrain(const T& x, Eigen::Index k, Lp& lp) {
99105
if (Jacobian) {
100106
return corr_matrix_constrain(x, k, lp);
101107
} else {
@@ -118,12 +124,16 @@ inline auto corr_matrix_constrain(const T& x, Eigen::Index k,
118124
* @tparam T A standard vector with inner type inheriting from
119125
* `Eigen::DenseBase` or a `var_value` with inner type inheriting from
120126
* `Eigen::DenseBase` with compile time dynamic rows and 1 column
127+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
128+
* convertable to this.
121129
* @param y Vector of unconstrained partial correlations
122130
* @param K Dimensionality of returned correlation matrix
123131
* @param[in,out] lp log density accumulator
124132
*/
125-
template <bool Jacobian, typename T, require_std_vector_t<T>* = nullptr>
126-
inline auto corr_matrix_constrain(const T& y, int K, return_type_t<T>& lp) {
133+
template <bool Jacobian, typename T, typename Lp,
134+
require_std_vector_t<T>* = nullptr,
135+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
136+
inline auto corr_matrix_constrain(const T& y, int K, Lp& lp) {
127137
return apply_vector_unary<T>::apply(y, [&lp, K](auto&& v) {
128138
return corr_matrix_constrain<Jacobian>(v, K, lp);
129139
});

stan/math/prim/constraint/cov_matrix_constrain.hpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,17 @@ cov_matrix_constrain(const T& x, Eigen::Index K) {
5555
*
5656
* @tparam T type of the vector (must be derived from \c Eigen::MatrixBase and
5757
* have one compile-time dimension equal to 1)
58+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
59+
* convertable to this.
5860
* @param x The vector to convert to a covariance matrix.
5961
* @param K The dimensions of the resulting covariance matrix.
6062
* @param lp Reference
6163
* @throws std::domain_error if (x.size() != K + (K choose 2)).
6264
*/
63-
template <typename T, require_eigen_col_vector_t<T>* = nullptr>
65+
template <typename T, typename Lp, require_eigen_col_vector_t<T>* = nullptr,
66+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
6467
inline Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic>
65-
cov_matrix_constrain(const T& x, Eigen::Index K, return_type_t<T>& lp) {
68+
cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) {
6669
using Eigen::Dynamic;
6770
using Eigen::Matrix;
6871
using std::exp;
@@ -99,14 +102,17 @@ cov_matrix_constrain(const T& x, Eigen::Index K, return_type_t<T>& lp) {
99102
* @tparam T A type inheriting from `Eigen::DenseBase` or a `var_value` with
100103
* inner type inheriting from `Eigen::DenseBase` with compile time dynamic rows
101104
* and 1 column
105+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
106+
* convertable to this.
102107
* @param x The vector to convert to a covariance matrix
103108
* @param K The dimensions of the resulting covariance matrix
104109
* @param[in, out] lp log density accumulator
105110
* @throws std::domain_error if (x.size() != K + (K choose 2)).
106111
*/
107-
template <bool Jacobian, typename T, require_not_std_vector_t<T>* = nullptr>
108-
inline auto cov_matrix_constrain(const T& x, Eigen::Index K,
109-
return_type_t<T>& lp) {
112+
template <bool Jacobian, typename T, typename Lp,
113+
require_not_std_vector_t<T>* = nullptr,
114+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
115+
inline auto cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) {
110116
if (Jacobian) {
111117
return cov_matrix_constrain(x, K, lp);
112118
} else {
@@ -127,14 +133,17 @@ inline auto cov_matrix_constrain(const T& x, Eigen::Index K,
127133
* @tparam T A standard vector with inner type inheriting from
128134
* `Eigen::DenseBase` or a `var_value` with inner type inheriting from
129135
* `Eigen::DenseBase` with compile time dynamic rows and 1 column
136+
* @tparam Lp A scalar type for the lp argument. The scalar type of T should be
137+
* convertable to this.
130138
* @param x The vector to convert to a covariance matrix
131139
* @param K The dimensions of the resulting covariance matrix
132140
* @param[in, out] lp log density accumulator
133141
* @throws std::domain_error if (x.size() != K + (K choose 2)).
134142
*/
135-
template <bool Jacobian, typename T, require_std_vector_t<T>* = nullptr>
136-
inline auto cov_matrix_constrain(const T& x, Eigen::Index K,
137-
return_type_t<T>& lp) {
143+
template <bool Jacobian, typename T, typename Lp,
144+
require_std_vector_t<T>* = nullptr,
145+
require_convertible_t<return_type_t<T>, Lp>* = nullptr>
146+
inline auto cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) {
138147
return apply_vector_unary<T>::apply(x, [&lp, K](auto&& v) {
139148
return cov_matrix_constrain<Jacobian>(v, K, lp);
140149
});

stan/math/prim/constraint/lb_constrain.hpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,17 @@ inline auto lb_constrain(const T& x, const L& lb) {
5050
*
5151
* @tparam T Scalar.
5252
* @tparam L Scalar.
53+
* @tparam Lp scalar, T and L should be convertible to this.
5354
* @param[in] x unconstrained input
5455
* @param[in] lb lower bound on output
5556
* @param[in,out] lp reference to log probability to increment
5657
* @return lower-bound constrained value corresponding to inputs
5758
*/
58-
template <typename T, typename L, require_all_stan_scalar_t<T, L>* = nullptr,
59-
require_all_not_st_var<T, L>* = nullptr>
60-
inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
59+
template <typename T, typename L, typename Lp,
60+
require_all_stan_scalar_t<T, L>* = nullptr,
61+
require_all_not_st_var<T, L>* = nullptr,
62+
require_convertible_t<return_type_t<T, L>, Lp>* = nullptr>
63+
inline auto lb_constrain(const T& x, const L& lb, Lp& lp) {
6164
if (value_of_rec(lb) == NEGATIVE_INFTY) {
6265
return identity_constrain(x, lb);
6366
} else {
@@ -89,15 +92,18 @@ inline auto lb_constrain(T&& x, L&& lb) {
8992
*
9093
* @tparam T A type inheriting from `EigenBase`.
9194
* @tparam L Scalar.
95+
* @tparam Lp scalar, T and L should be convertible to this.
9296
* @param[in] x unconstrained input
9397
* @param[in] lb lower bound on output
9498
* @param[in,out] lp reference to log probability to increment
9599
* @return lower-bound constrained value corresponding to inputs
96100
*/
97-
template <typename T, typename L, require_eigen_t<T>* = nullptr,
101+
template <typename T, typename L, typename Lp, require_eigen_t<T>* = nullptr,
98102
require_stan_scalar_t<L>* = nullptr,
99-
require_all_not_st_var<T, L>* = nullptr>
100-
inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
103+
require_all_not_st_var<T, L>* = nullptr,
104+
require_convertible_t<return_type_t<T, L>, Lp>* = nullptr>
105+
106+
inline auto lb_constrain(const T& x, const L& lb, Lp& lp) {
101107
return eval(
102108
x.unaryExpr([lb, &lp](auto&& xx) { return lb_constrain(xx, lb, lp); }));
103109
}
@@ -126,14 +132,17 @@ inline auto lb_constrain(T&& x, L&& lb) {
126132
*
127133
* @tparam T A type inheriting from `EigenBase`.
128134
* @tparam L A type inheriting from `EigenBase`.
135+
* @tparam Lp Scalar, the scalar type of T and L should be convertible to this.
129136
* @param[in] x unconstrained input
130137
* @param[in] lb lower bound on output
131138
* @param[in,out] lp reference to log probability to increment
132139
* @return lower-bound constrained value corresponding to inputs
133140
*/
134-
template <typename T, typename L, require_all_eigen_t<T, L>* = nullptr,
135-
require_all_not_st_var<T, L>* = nullptr>
136-
inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
141+
template <typename T, typename L, typename Lp,
142+
require_all_eigen_t<T, L>* = nullptr,
143+
require_all_not_st_var<T, L>* = nullptr,
144+
require_convertible_t<return_type_t<T, L>, Lp>* = nullptr>
145+
inline auto lb_constrain(const T& x, const L& lb, Lp& lp) {
137146
check_matching_dims("lb_constrain", "x", x, "lb", lb);
138147
return eval(x.binaryExpr(
139148
lb, [&lp](auto&& xx, auto&& lbb) { return lb_constrain(xx, lbb, lp); }));
@@ -164,14 +173,16 @@ inline auto lb_constrain(const std::vector<T>& x, const L& lb) {
164173
*
165174
* @tparam T A Any type with a Scalar `scalar_type`.
166175
* @tparam L A type inheriting from `EigenBase` or a standard vector.
176+
* @tparam Lp Scalar, T and the scalar type of L should be convertible to this.
167177
* @param[in] x unconstrained input
168178
* @param[in] lb lower bound on output
169179
* @param[in,out] lp reference to log probability to increment
170180
* @return lower-bound constrained value corresponding to inputs
171181
*/
172-
template <typename T, typename L, require_not_std_vector_t<L>* = nullptr>
173-
inline auto lb_constrain(const std::vector<T>& x, const L& lb,
174-
return_type_t<T, L>& lp) {
182+
template <typename T, typename L, typename Lp,
183+
require_not_std_vector_t<L>* = nullptr,
184+
require_convertible_t<return_type_t<T, L>, Lp>* = nullptr>
185+
inline auto lb_constrain(const std::vector<T>& x, const L& lb, Lp& lp) {
175186
std::vector<plain_type_t<decltype(lb_constrain(x[0], lb))>> ret(x.size());
176187
for (size_t i = 0; i < x.size(); ++i) {
177188
ret[i] = lb_constrain(x[i], lb, lp);
@@ -205,14 +216,16 @@ inline auto lb_constrain(const std::vector<T>& x, const std::vector<L>& lb) {
205216
*
206217
* @tparam T A Any type with a Scalar `scalar_type`.
207218
* @tparam L A type inheriting from `EigenBase` or a standard vector.
219+
* @tparam Lp Scalar, T and the scalar type of L should be convertible to this.
208220
* @param[in] x unconstrained input
209221
* @param[in] lb lower bound on output
210222
* @param[in,out] lp reference to log probability to increment
211223
* @return lower-bound constrained value corresponding to inputs
212224
*/
213-
template <typename T, typename L>
225+
template <typename T, typename L, typename Lp,
226+
require_convertible_t<return_type_t<T, L>, Lp>* = nullptr>
214227
inline auto lb_constrain(const std::vector<T>& x, const std::vector<L>& lb,
215-
return_type_t<T, L>& lp) {
228+
Lp& lp) {
216229
check_matching_dims("lb_constrain", "x", x, "lb", lb);
217230
std::vector<plain_type_t<decltype(lb_constrain(x[0], lb[0]))>> ret(x.size());
218231
for (size_t i = 0; i < x.size(); ++i) {
@@ -234,13 +247,15 @@ inline auto lb_constrain(const std::vector<T>& x, const std::vector<L>& lb,
234247
* type inheriting from `Eigen::EigenBase`, a standard vector, or a scalar
235248
* @tparam L A type inheriting from `Eigen::EigenBase`, a `var_value` with inner
236249
* type inheriting from `Eigen::EigenBase`, a standard vector, or a scalar
250+
* @tparam Lp Scalar, the scalar type of T and L should be convertible to this.
237251
* @param[in] x unconstrained input
238252
* @param[in] lb lower bound on output
239253
* @param[in, out] lp log density accumulator
240254
* @return lower-bound constrained value corresponding to inputs
241255
*/
242-
template <bool Jacobian, typename T, typename L>
243-
inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
256+
template <bool Jacobian, typename T, typename L, typename Lp,
257+
require_convertible_t<return_type_t<T, L>, Lp>* = nullptr>
258+
inline auto lb_constrain(const T& x, const L& lb, Lp& lp) {
244259
if (Jacobian) {
245260
return lb_constrain(x, lb, lp);
246261
} else {

0 commit comments

Comments
 (0)