Skip to content

Commit 558530e

Browse files
authored
Merge pull request #2382 from stan-dev/feature/lb_constrain-matvar_varmat_tests
Feature/lb constrain matvar varmat tests
2 parents a4abbe2 + ab230e6 commit 558530e

File tree

7 files changed

+730
-254
lines changed

7 files changed

+730
-254
lines changed

stan/math/prim/fun/lb_constrain.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
115115
template <typename T, typename L, require_all_eigen_t<T, L>* = nullptr,
116116
require_all_not_st_var<T, L>* = nullptr>
117117
inline auto lb_constrain(T&& x, L&& lb) {
118+
check_matching_dims("lb_constrain", "x", x, "lb", lb);
118119
return eval(x.binaryExpr(
119120
lb, [](auto&& x, auto&& lb) { return lb_constrain(x, lb); }));
120121
}
@@ -133,6 +134,7 @@ inline auto lb_constrain(T&& x, L&& lb) {
133134
template <typename T, typename L, require_all_eigen_t<T, L>* = nullptr,
134135
require_all_not_st_var<T, L>* = nullptr>
135136
inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
137+
check_matching_dims("lb_constrain", "x", x, "lb", lb);
136138
return eval(x.binaryExpr(
137139
lb, [&lp](auto&& xx, auto&& lbb) { return lb_constrain(xx, lbb, lp); }));
138140
}
@@ -189,6 +191,7 @@ inline auto lb_constrain(const std::vector<T>& x, const L& lb,
189191
*/
190192
template <typename T, typename L>
191193
inline auto lb_constrain(const std::vector<T>& x, const std::vector<L>& lb) {
194+
check_matching_dims("lb_constrain", "x", x, "lb", lb);
192195
std::vector<plain_type_t<decltype(lb_constrain(x[0], lb[0]))>> ret(x.size());
193196
for (size_t i = 0; i < x.size(); ++i) {
194197
ret[i] = lb_constrain(x[i], lb[i]);
@@ -210,6 +213,7 @@ inline auto lb_constrain(const std::vector<T>& x, const std::vector<L>& lb) {
210213
template <typename T, typename L>
211214
inline auto lb_constrain(const std::vector<T>& x, const std::vector<L>& lb,
212215
return_type_t<T, L>& lp) {
216+
check_matching_dims("lb_constrain", "x", x, "lb", lb);
213217
std::vector<plain_type_t<decltype(lb_constrain(x[0], lb[0]))>> ret(x.size());
214218
for (size_t i = 0; i < x.size(); ++i) {
215219
ret[i] = lb_constrain(x[i], lb[i], lp);

stan/math/rev/fun/lb_constrain.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
234234
template <typename T, typename L, require_all_matrix_t<T, L>* = nullptr,
235235
require_any_st_var<T, L>* = nullptr>
236236
inline auto lb_constrain(const T& x, const L& lb) {
237+
check_matching_dims("lb_constrain", "x", x, "lb", lb);
237238
using ret_type = return_var_matrix_t<T, T, L>;
238239
if (!is_constant<T>::value && !is_constant<L>::value) {
239240
arena_t<promote_scalar_t<var, T>> arena_x = x;
@@ -297,6 +298,7 @@ inline auto lb_constrain(const T& x, const L& lb) {
297298
template <typename T, typename L, require_all_matrix_t<T, L>* = nullptr,
298299
require_any_st_var<T, L>* = nullptr>
299300
inline auto lb_constrain(const T& x, const L& lb, return_type_t<T, L>& lp) {
301+
check_matching_dims("lb_constrain", "x", x, "lb", lb);
300302
using ret_type = return_var_matrix_t<T, T, L>;
301303
if (!is_constant<T>::value && !is_constant<L>::value) {
302304
arena_t<promote_scalar_t<var, T>> arena_x = x;

test/unit/math/mix/fun/lb_constrain_matvar_test.cpp

+106
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@ void expect_matvar(const T1& x, const T2& lb) {
2727
stan::test::expect_ad_matvar(f3, x, lb);
2828
stan::test::expect_ad_matvar(f4, x, lb);
2929
}
30+
31+
template <typename T1, typename T2>
32+
void expect_vec_matvar(const T1& x, const T2& lb) {
33+
auto f1 = [](const auto& x, const auto& lb) {
34+
return stan::math::lb_constrain(x, lb);
35+
};
36+
auto f2 = [](const auto& x, const auto& lb) {
37+
stan::return_type_t<decltype(x), decltype(lb)> lp = 0;
38+
return stan::math::lb_constrain(x, lb, lp);
39+
};
40+
auto f3 = [](const auto& x, const auto& lb) {
41+
stan::return_type_t<decltype(x), decltype(lb)> lp = 0;
42+
stan::math::lb_constrain(x, lb, lp);
43+
return lp;
44+
};
45+
auto f4 = [](const auto& x, const auto& lb) {
46+
stan::return_type_t<decltype(x), decltype(lb)> lp = 0;
47+
auto xx = stan::math::eval(stan::math::lb_constrain(x, lb, lp));
48+
stan::return_type_t<decltype(x), decltype(lb)> xx_acc = 0;
49+
for (size_t i = 0; i < xx.size(); ++i) {
50+
xx_acc += stan::math::sum(xx[i]);
51+
}
52+
return stan::math::add(lp, xx_acc);
53+
};
54+
stan::test::expect_ad_matvar(f1, x, lb);
55+
stan::test::expect_ad_matvar(f2, x, lb);
56+
stan::test::expect_ad_matvar(f3, x, lb);
57+
stan::test::expect_ad_matvar(f4, x, lb);
58+
}
3059
} // namespace lb_constrain_test
3160

3261
TEST(mathMixMatFun, lb_matvar_constrain) {
@@ -37,7 +66,10 @@ TEST(mathMixMatFun, lb_matvar_constrain) {
3766
A << 5.0, 2.0, 0.0, 0.005;
3867
Eigen::MatrixXd lbm(2, 2);
3968
lbm << 7.0, 5.0, 0.0, 0.0005;
69+
Eigen::MatrixXd lbm_bad(2, 1);
70+
lbm_bad << 7.0, 5.0;
4071
lb_constrain_test::expect_matvar(A, lbm);
72+
lb_constrain_test::expect_matvar(A, lbm_bad);
4173
double lbd = 6.0;
4274
lb_constrain_test::expect_matvar(A, lbd);
4375
}
@@ -50,3 +82,77 @@ TEST(mathMixMatFun, lb_matvar_constrain_neg_inf) {
5082
lb_constrain_test::expect_matvar(A, lbm);
5183
lb_constrain_test::expect_matvar(A, stan::math::NEGATIVE_INFTY);
5284
}
85+
86+
// matrix[], matrix
87+
// matrix[], real
88+
TEST(mathMixMatFun, lb_stdvec_mat_mat_constrain_matvar) {
89+
Eigen::MatrixXd A_inner(2, 3);
90+
A_inner << 5.0, 2.0, 4.0, -2.0, 0.0, 0.005;
91+
Eigen::MatrixXd lbm_inner(2, 3);
92+
lbm_inner << 7.0, 5.0, 6.0, 100.0, 0.0, 0.0005;
93+
Eigen::MatrixXd lbm_inner_bad(2, 2);
94+
lbm_inner_bad << 7.0, 5.0, 6.0, 100.0;
95+
Eigen::MatrixXd A_inner2 = 2.0 * A_inner;
96+
std::vector<Eigen::MatrixXd> A;
97+
A.push_back(A_inner);
98+
A.push_back(A_inner2);
99+
lb_constrain_test::expect_vec_matvar(A, lbm_inner);
100+
lb_constrain_test::expect_vec_matvar(A, lbm_inner_bad);
101+
double lbd = 6.0;
102+
lb_constrain_test::expect_vec_matvar(A, lbd);
103+
}
104+
105+
TEST(mathMixMatFun, lb_stdvec_mat_mat_constrain_matvar_neg_inf) {
106+
Eigen::MatrixXd A_inner(2, 3);
107+
A_inner << 5.0, 2.0, 4.0, -2.0, 0.0, 0.005;
108+
Eigen::MatrixXd lbm_inner(2, 3);
109+
lbm_inner << 7.0, 5.0, 6.0, stan::math::NEGATIVE_INFTY, 0.0, 0.0005;
110+
Eigen::MatrixXd A_inner2 = 2.0 * A_inner;
111+
std::vector<Eigen::MatrixXd> A;
112+
A.push_back(A_inner);
113+
A.push_back(A_inner2);
114+
lb_constrain_test::expect_vec_matvar(A, lbm_inner);
115+
double lbi = stan::math::NEGATIVE_INFTY;
116+
lb_constrain_test::expect_vec_matvar(A, lbi);
117+
}
118+
119+
// matrix[], matrix[]
120+
TEST(mathMixMatFun, lb_stdvec_mat_constrain_matvar) {
121+
Eigen::MatrixXd A_inner(2, 3);
122+
A_inner << 5.0, 2.0, 4.0, -2.0, 0.0, 0.005;
123+
Eigen::MatrixXd lbm_inner(2, 3);
124+
lbm_inner << 7.0, 5.0, 6.0, 100.0, 0.0, 0.0005;
125+
Eigen::MatrixXd A_inner2 = 2.0 * A_inner;
126+
Eigen::MatrixXd lbm_inner2 = 3.0 * lbm_inner;
127+
std::vector<Eigen::MatrixXd> A;
128+
A.push_back(A_inner);
129+
A.push_back(A_inner2);
130+
std::vector<Eigen::MatrixXd> lbm;
131+
lbm.push_back(lbm_inner);
132+
lbm.push_back(lbm_inner2);
133+
std::vector<Eigen::MatrixXd> lbm_bad1;
134+
lbm_bad1.push_back(lbm_inner);
135+
Eigen::MatrixXd lbm_inner_bad(2, 2);
136+
lbm_inner_bad << 7.0, 5.0, 6.0, 100.0;
137+
std::vector<Eigen::MatrixXd> lbm_bad2;
138+
lbm_bad2.push_back(lbm_inner_bad);
139+
lb_constrain_test::expect_vec_matvar(A, lbm);
140+
lb_constrain_test::expect_vec_matvar(A, lbm_bad1);
141+
lb_constrain_test::expect_vec_matvar(A, lbm_bad2);
142+
}
143+
144+
TEST(mathMixMatFun, lb_stdvec_mat_constrain_matvar_neg_inf) {
145+
Eigen::MatrixXd A_inner(2, 2);
146+
A_inner << 5.0, 2.0, 4.0, -2.0;
147+
Eigen::MatrixXd lbm_inner(2, 2);
148+
lbm_inner << 7.0, 5.0, stan::math::NEGATIVE_INFTY, 100.0;
149+
Eigen::MatrixXd A_inner2 = 2 * A_inner;
150+
Eigen::MatrixXd lbm_inner2(2, 2);
151+
lbm_inner << 7.0, stan::math::NEGATIVE_INFTY, 5.0, 100.0;
152+
std::vector<Eigen::MatrixXd> A{A_inner, A_inner2};
153+
std::vector<Eigen::MatrixXd> lbm{lbm_inner, lbm_inner2};
154+
lb_constrain_test::expect_vec_matvar(A, lbm);
155+
lb_constrain_test::expect_vec_matvar(A, A_inner);
156+
lb_constrain_test::expect_vec_matvar(A, stan::math::NEGATIVE_INFTY);
157+
}
158+

test/unit/math/mix/fun/lb_constrain_test.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ TEST(mathMixMatFun, lb_mat_constrain) {
7777
A << 5.0, 2.0, 4.0, -2.0, 0.0, 0.005;
7878
Eigen::MatrixXd lbm(2, 3);
7979
lbm << 7.0, 5.0, 6.0, 100.0, 0.0, 0.0005;
80+
Eigen::MatrixXd lbm_bad(2, 2);
81+
lbm_bad << 7.0, 5.0, 6.0, 100.0;
8082
lb_constrain_test::expect(A, lbm);
83+
lb_constrain_test::expect(A, lbm_bad);
8184
double lbd = 6.0;
8285
lb_constrain_test::expect(A, lbd);
8386
}
@@ -96,7 +99,9 @@ TEST(mathMixMatFun, lb_mat_constrain_neg_inf) {
9699
TEST(mathMixMatFun, lb_stdvec_constrain) {
97100
std::vector<double> A{5.0, 2.0, 4.0, -2.0};
98101
std::vector<double> lbm{7.0, 5.0, 6.0, 100.0};
102+
std::vector<double> lbm_bad{7.0, 5.0, 6.0};
99103
lb_constrain_test::expect(A, lbm);
104+
lb_constrain_test::expect(A, lbm_bad);
100105
double lbd = 6.0;
101106
lb_constrain_test::expect(A, lbd);
102107
}
@@ -115,11 +120,14 @@ TEST(mathMixMatFun, lb_stdvec_mat_mat_constrain) {
115120
A_inner << 5.0, 2.0, 4.0, -2.0, 0.0, 0.005;
116121
Eigen::MatrixXd lbm_inner(2, 3);
117122
lbm_inner << 7.0, 5.0, 6.0, 100.0, 0.0, 0.0005;
123+
Eigen::MatrixXd lbm_inner_bad(2, 1);
124+
lbm_inner_bad << 7.0, 5.0;
118125
Eigen::MatrixXd A_inner2 = 2.0 * A_inner;
119126
std::vector<Eigen::MatrixXd> A;
120127
A.push_back(A_inner);
121128
A.push_back(A_inner2);
122129
lb_constrain_test::expect_vec(A, lbm_inner);
130+
lb_constrain_test::expect_vec(A, lbm_inner_bad);
123131
double lbd = 6.0;
124132
lb_constrain_test::expect_vec(A, lbd);
125133
}
@@ -152,7 +160,15 @@ TEST(mathMixMatFun, lb_stdvec_mat_constrain) {
152160
std::vector<Eigen::MatrixXd> lbm;
153161
lbm.push_back(lbm_inner);
154162
lbm.push_back(lbm_inner2);
163+
std::vector<Eigen::MatrixXd> lbm_bad1;
164+
lbm_bad1.push_back(lbm_inner);
165+
Eigen::MatrixXd lbm_inner_bad(2, 2);
166+
lbm_inner_bad << 7.0, 5.0, 6.0, 100.0;
167+
std::vector<Eigen::MatrixXd> lbm_bad2;
168+
lbm_bad2.push_back(lbm_inner_bad);
155169
lb_constrain_test::expect_vec(A, lbm);
170+
lb_constrain_test::expect_vec(A, lbm_bad1);
171+
lb_constrain_test::expect_vec(A, lbm_bad2);
156172
}
157173

158174
TEST(mathMixMatFun, lb_stdvec_mat_constrain_neg_inf) {

0 commit comments

Comments
 (0)