Repository navigation
matrix and array ad tests to framework - #1424
Conversation
…re/1385-update-autodiff-tests
|
(stat_comp_benchmarks/benchmarks/gp_pois_regr/gp_pois_regr.stan, 1.0) |
|
I started reviewing this one. Just posting here so we dont duplicate any efforts. Will probably take me some time. |
|
Thanks! Ben Bales took the hit on the first one. This one's a lot bigger, but it's also more boilerplate.
|
rok-cesnovar
left a comment
There was a problem hiding this comment.
This is fantastic stuff and it was a ton of work! I really dont have any major comments.
The only minor comment that I think should be addressed is the use of boost::promote_args that should be replaced by our type trait return_type_t. I know that there are a few places in Math where we still use boost::promote args directly, but we did mostly clean it up.
The other one is zero-sized input tests. Some of them are missing and they were already missing before so this may be out of scope of this PR. If you feel so, I will make a separate issue with the files I flagged here. I figured if I am already going through might as well check & flag that.
|
Thanks for reviewing. I can make those changes to promote_args.
Most of the missing tests are because we don't have consistent boundary and exception behavior. We really need to audit the entire API. This has come up again w.r.t. sampling and inverse logit boundaries.
In general, there are also missing infinite and NaN input test cases for the same reason---inconsistent excpetion/boundary behavior across our autodiff levels.
… On Oct 31, 2019, at 8:32 AM, Rok Češnovar ***@***.***> wrote:
@rok-cesnovar requested changes on this pull request.
This is fantastic stuff and it was a ton of work! I really dont have any major comments.
The only minor comment that I think should be addressed is the use of boost::promote_args that should be replaced by our type trait return_type_t. I know that there are a few places in Math where we still use boost::promote args directly, but we did mostly clean it up.
The other one is zero-sized input tests. Some of them are missing and they were already missing before so this may be out of scope of this PR. If you feel so, I will make a separate issue with the files I flagged here. I figured if I am already going through might as well check & flag that.
In test/unit/math/mix/scal/fun/ub_constrain_test.cpp:
> @@ -0,0 +1,35 @@
+#include <test/unit/math/test_ad.hpp>
+#include <limits>
+
+template <typename T, typename U>
+typename boost::math::tools::promote_args<T, U>::type g1(const T& x,
Same as the previous comment.
It might be better to just use the Stan Math type trait return_type_t here.
return_type_t<T,U> g1(const T& x,...
Same goes for the other two uses of promote_args in this file.
In test/unit/math/mix/mat/fun/add_test.cpp:
> + Eigen::VectorXd rv5b(5);
+ v5 << 2, 3, 4, 5, 6;
+ stan::test::expect_ad(f, v5, v5b);
+ stan::test::expect_ad(f, rv5, rv5b);
+
+ Eigen::MatrixXd m22c(2, 2);
+ m22c << -10, 1, 10, 0;
+ Eigen::MatrixXd m22d(2, 2);
+ m22d << 10, -10, 1, 2;
+ stan::test::expect_ad(f, m22c, m22d);
+
+ Eigen::MatrixXd m23(2, 3);
+ m23 << 1, 2, 3, 4, 5, 6;
+ Eigen::MatrixXd m23b(2, 3);
+ m23b << 10, 12, 14, -1, -3, -10;
+ stan::test::expect_ad(f, m23, m23b);
I dont see any test for zero-sized matrices as input here. Should we also maybe test that?
In test/unit/math/mix/mat/fun/corr_matrix_constrain_test.cpp:
> + tols.hessian_fvar_hessian_ = 1e-2;
+
+ auto f1 = [](const auto& x) { return g1(x); };
+ auto f2 = [](const auto& x) { return g2(x); };
+ auto f3 = [](const auto& x) { return g3(x); };
+ stan::test::expect_ad(f1, x);
+ stan::test::expect_ad(f2, x);
+ stan::test::expect_ad(tols, f3, x);
+}
+
+TEST(MathMixMatFun, corr_matrixTransform) {
+ // sizes must be (n choose 2)
+
+ // TODO(carpenter): this doesn't work but should; fix transform
+ // Eigen::VectorXd v0(0);
+ // expect_corr_matrix_transform(v0);
This probably deserves a separate issue so it doesnt get forgotten?
In test/unit/math/mix/mat/fun/cov_matrix_constrain_test.cpp:
> +void expect_cov_matrix_transform(const T& x) {
+ stan::test::ad_tolerances tols;
+ tols.hessian_hessian_ = 1e-2;
+ tols.hessian_fvar_hessian_ = 1e-2;
+
+ auto f1 = [](const auto& x) { return g1(x); };
+ auto f2 = [](const auto& x) { return g2(x); };
+ auto f3 = [](const auto& x) { return g3(x); };
+ stan::test::expect_ad(f1, x);
+ stan::test::expect_ad(f2, x);
+ stan::test::expect_ad(tols, f3, x);
+}
+
+TEST(MathMixMatFun, cov_matrixTransform) {
+ // sizes must be n + (n choose 2)
+
Should we also test for zero size here?
In test/unit/math/mix/mat/fun/crossprod_test.cpp:
>
-TEST(AgradMixMatrixCrossProd, 3x3_matrix_fv_1stderiv) {
- using stan::math::fvar;
- using stan::math::matrix_d;
- using stan::math::matrix_fv;
- using stan::math::var;
+TEST(MathMixMatFun, crossprod) {
+ auto f = [](const auto& y) { return stan::math::crossprod(y); };
Zero-sized input test?
In test/unit/math/mix/mat/fun/determinant_test.cpp:
>
- matrix_fv a(2, 2);
- a << b, c, d, e;
+ // primitive errors don't match
+ // Eigen::MatrixXd z(0, 0);
Should this be a separate issue that needs resolving?
In test/unit/math/mix/mat/fun/append_col_test.cpp:
> - vars.push_back(a(3).val_.val_);
-
- std::vector<double> grads;
- ab_append_col(0).d_.d_.grad(vars, grads);
- EXPECT_FLOAT_EQ(0, grads[0]);
- EXPECT_FLOAT_EQ(0, grads[1]);
- EXPECT_FLOAT_EQ(0, grads[2]);
- EXPECT_FLOAT_EQ(0, grads[3]);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, appendCol) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::append_col(x, y);
+ };
+
+ Eigen::MatrixXd m22(2, 2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/append_row_test.cpp:
> - vars.push_back(a(3).val_.val_);
-
- std::vector<double> grads;
- ab_append_row(0).d_.d_.grad(vars, grads);
- EXPECT_FLOAT_EQ(0, grads[0]);
- EXPECT_FLOAT_EQ(0, grads[1]);
- EXPECT_FLOAT_EQ(0, grads[2]);
- EXPECT_FLOAT_EQ(0, grads[3]);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, appendRow) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::append_row(x, y);
+ };
+
+ Eigen::MatrixXd m22(2, 2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/columns_dot_product_test.cpp:
> - EXPECT_THROW(columns_dot_product(d2, v1), std::invalid_argument);
- EXPECT_THROW(columns_dot_product(d2, v2), std::invalid_argument);
- EXPECT_THROW(columns_dot_product(d2, v5), std::invalid_argument);
- EXPECT_THROW(columns_dot_product(d2, v6), std::invalid_argument);
-
- EXPECT_THROW(columns_dot_product(d3, v1), std::invalid_argument);
- EXPECT_THROW(columns_dot_product(d3, v2), std::invalid_argument);
- EXPECT_THROW(columns_dot_product(d3, v3), std::invalid_argument);
- EXPECT_THROW(columns_dot_product(d3, v4), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, columnsDotProduct) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::columns_dot_product(x, y);
+ };
+ Eigen::VectorXd u3(3);
Zero-sized input test?
In test/unit/math/mix/mat/fun/columns_dot_self_test.cpp:
> - m3 << a, b, c, d;
- x = columns_dot_self(m3);
-
- AVEC z
- = createAVEC(a.val().val(), b.val().val(), c.val().val(), d.val().val());
- VEC h;
- x(0, 0).d_.d_.grad(z, h);
- EXPECT_FLOAT_EQ(0.0, h[0]);
- EXPECT_FLOAT_EQ(0.0, h[1]);
- EXPECT_FLOAT_EQ(0.0, h[2]);
- EXPECT_FLOAT_EQ(0.0, h[3]);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, columnsDotSelf) {
+ auto f = [](const auto& x) { return stan::math::columns_dot_self(x); };
+ Eigen::MatrixXd a11(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/divide_test.cpp:
> @@ -0,0 +1,33 @@
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, divide) {
+ auto f
+ = [](const auto& x, const auto& y) { return stan::math::divide(x, y); };
+
+ double x1 = 10;
+ double x2 = -2;
+ stan::test::expect_ad(f, x1, x2);
+
+ Eigen::VectorXd v(1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/dot_self_test.cpp:
>
- fvar<var> a(2.0, 1.0);
- fvar<var> b(3.0, 1.0);
- fvar<var> c(4.0, 1.0);
+ Eigen::VectorXd x1(1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/elt_divide_test.cpp:
> - VEC hh;
- z(0).d_.d_.grad(q, hh);
- EXPECT_FLOAT_EQ(-0.001200000, hh[0]);
- EXPECT_FLOAT_EQ(0.0, hh[1]);
- EXPECT_FLOAT_EQ(0.0, hh[2]);
- EXPECT_FLOAT_EQ(0.0, hh[3]);
- EXPECT_FLOAT_EQ(0.0, hh[4]);
- EXPECT_FLOAT_EQ(0.0, hh[5]);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, eltDivide) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::elt_divide(x, y);
+ };
+
+ Eigen::VectorXd a2(2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/elt_multiply_test.cpp:
> - VEC hh;
- z(0).d_.d_.grad(q, hh);
- EXPECT_FLOAT_EQ(0, hh[0]);
- EXPECT_FLOAT_EQ(0.0, hh[1]);
- EXPECT_FLOAT_EQ(0.0, hh[2]);
- EXPECT_FLOAT_EQ(0.0, hh[3]);
- EXPECT_FLOAT_EQ(0.0, hh[4]);
- EXPECT_FLOAT_EQ(0.0, hh[5]);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, eltMultiply) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::elt_multiply(x, y);
+ };
+
+ Eigen::VectorXd a2(2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/inverse_spd_test.cpp:
> - stan::math::recover_memory();
- for (int k = 0; k < 9; k++)
- EXPECT_FLOAT_EQ(h1[k], h2[k]);
- }
- }
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, inverseSpd) {
+ auto f = [](const auto& x) {
+ if (x.rows() != x.cols())
+ return stan::math::inverse_spd(x);
+ auto y = ((x + x.transpose()) * 0.5).eval(); // symmetry for finite diffs
+ return stan::math::inverse_spd(y);
+ };
+
+ Eigen::MatrixXd a(2, 2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/log_determinant_ldlt_test.cpp:
> - VEC h;
- det.d_.d_.grad(q, h);
- EXPECT_FLOAT_EQ(0.18518518, h[0]);
- EXPECT_FLOAT_EQ(0, h[1]);
- EXPECT_FLOAT_EQ(0.33333333, h[2]);
- EXPECT_FLOAT_EQ(0.14583333, h[3]);
+#include <test/unit/math/test_ad.hpp>
+#include <vector>
+
+TEST(MathMixMatFun, logDeterminantLdlt) {
+ auto f = [](const auto& x) {
+ auto y = stan::test::ldlt_factor(x);
+ return stan::math::log_determinant_ldlt(y);
+ };
+
+ Eigen::MatrixXd a(2, 2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/log_determinant_spd_test.cpp:
> - using stan::math::matrix_ffv;
-
- EXPECT_THROW(log_determinant_spd(matrix_ffv(2, 3)), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+#include <vector>
+
+TEST(MathMixMatFun, logDeterminantSpd) {
+ auto f = [](const auto& x) {
+ auto z = ((x + x.transpose()) * 0.5).eval();
+ return stan::math::log_determinant_spd(z);
+ };
+
+ // for testing error conditions
+ auto g = [](const auto& x) { return stan::math::log_determinant_spd(x); };
+
+ Eigen::MatrixXd a(2, 2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/log_determinant_test.cpp:
> - EXPECT_FLOAT_EQ(-1, h[2]);
- EXPECT_FLOAT_EQ(0.75, h[3]);
-}
-TEST(AgradMixMatrixLogDeterminant, ffv_exception) {
- using stan::math::log_determinant;
- using stan::math::matrix_ffv;
-
- EXPECT_THROW(log_determinant(matrix_ffv(2, 3)), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+#include <vector>
+
+TEST(MathMixMatFun, logDeterminant) {
+ auto f = [](const auto& x) { return stan::math::log_determinant(x); };
+
+ // repeat symmetric pos def tests
+ Eigen::MatrixXd a(2, 2);
Zero-sized input test?
In test/unit/math/mix/mat/fun/log_sum_exp_test.cpp:
>
-TEST(AgradMixMatrixLogSumExp, vector_fv_1st_deriv) {
- using stan::math::vector_fv;
+ // TODO(carpenter): fix log_sum_exp boundary behavior
+ // Eigen::VectorXd x0(0);
+ // stan::test::expect_ad(f, x0);
This one already has a separate issue so maybe just remove the comment. I will handle that issue once this is merged.
In test/unit/math/mix/mat/fun/matrix_exp_multiply_test.cpp:
> + };
+ Eigen::MatrixXd a = Eigen::MatrixXd::Random(n, n);
+ Eigen::MatrixXd b = Eigen::MatrixXd::Random(n, m);
+ stan::test::expect_ad(f, a, b);
+}
+
+TEST(MathMixMatFun, matrixExpMultiply) {
+ auto f = [](const auto& x, auto& y) {
+ return stan::math::matrix_exp_multiply(x, y);
+ };
+
+ stan::test::ad_tolerances tols;
+ tols.hessian_hessian_ = 1e-2;
+ tols.hessian_fvar_hessian_ = 1e-2;
+
+ Eigen::MatrixXd a(5, 5);
Zero-sized input test?
In test/unit/math/mix/mat/fun/matrix_exp_pade_test.cpp:
> @@ -0,0 +1,36 @@
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, matrixExpPade) {
+ auto f = [](const auto& x) { return stan::math::matrix_exp_pade(x); };
+
+ Eigen::MatrixXd a1(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/matrix_exp_test.cpp:
> @@ -0,0 +1,42 @@
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, matrixExp) {
+ auto f = [](const auto& x) { return stan::math::matrix_exp(x); };
+
+ Eigen::MatrixXd a1(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_left_ldlt_test.cpp:
> - EXPECT_THROW(mdivide_left_ldlt(fv2, vf1), std::invalid_argument);
- EXPECT_THROW(mdivide_left_ldlt(fv2, vd1), std::invalid_argument);
- EXPECT_THROW(mdivide_left_ldlt(fd1, rvf2), std::invalid_argument);
- EXPECT_THROW(mdivide_left_ldlt(fd1, rvf1), std::invalid_argument);
- EXPECT_THROW(mdivide_left_ldlt(fd1, vf2), std::invalid_argument);
- EXPECT_THROW(mdivide_left_ldlt(fd2, rvf2), std::invalid_argument);
- EXPECT_THROW(mdivide_left_ldlt(fd2, rvf1), std::invalid_argument);
- EXPECT_THROW(mdivide_left_ldlt(fd2, vf1), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, mdivideLeftLdlt) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::mdivide_left_ldlt(stan::test::ldlt_factor(x), y);
+ };
+
+ Eigen::MatrixXd a(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_left_spd_test.cpp:
> - /* EXPECT_THROW(mdivide_left_spd(fd2, rvf2), std::domain_error);
- EXPECT_THROW(mdivide_left_spd(fd2, rvf1), std::domain_error);
- EXPECT_THROW(mdivide_left_spd(fd2, vf1), std::domain_error);
- */
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, mdivideLeftSpd) {
+ auto f = [](const auto& x, const auto& y) {
+ if (x.rows() != x.cols())
+ return stan::math::mdivide_left_spd(x, y);
+ auto x_sym = ((x + x.transpose()) * 0.5).eval(); // sym for finite diffs
+ return stan::math::mdivide_left_spd(x_sym, y);
+ };
+
+ // signature 1 of 2: matrix-matrix
+ Eigen::MatrixXd aa(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_left_test.cpp:
> - EXPECT_THROW(mdivide_left(fd2, rvf2), std::invalid_argument);
- EXPECT_THROW(mdivide_left(fd2, rvf1), std::invalid_argument);
- EXPECT_THROW(mdivide_left(fd2, vf1), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+#include <vector>
+
+TEST(MathMixMatFun, mdivideLeft) {
+ auto f = [](const auto& x, const auto& y) {
+ if (x.rows() != x.cols())
+ return stan::math::mdivide_left(x, y);
+ auto x_sym = ((x + x.transpose()) * 0.5).eval(); // sym for finite diffs
+ return stan::math::mdivide_left(x_sym, y);
+ };
+
+ // signature 1 of 2: matrix-matrix
+ Eigen::MatrixXd aa(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_left_tri_low_test.cpp:
> - vm2.setZero();
-
- EXPECT_THROW(mdivide_left_tri_low(fvm1, fvm2), std::invalid_argument);
- EXPECT_THROW(mdivide_left_tri_low(fvm1, vm2), std::invalid_argument);
- EXPECT_THROW(mdivide_left_tri_low(vm1, fvm2), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+#include <limits>
+
+TEST(MathMixMatFun, mdivideLeftTriLow) {
+ auto f = [](const auto& x, const auto& y) {
+ // no need to symmetrize becuase only uses view
+ return stan::math::mdivide_left_tri_low(x, y);
+ };
+
+ // signature 1 of 2: matrix-matrix
+ Eigen::MatrixXd aa(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_left_tri_test.cpp:
> - I(0, 0).d_.d_.grad(vars, grads);
- EXPECT_FLOAT_EQ(-0.09375, grads[0]);
- EXPECT_FLOAT_EQ(-0.11689815, grads[1]);
- EXPECT_FLOAT_EQ(0, grads[2]);
- EXPECT_FLOAT_EQ(-0.069733799, grads[3]);
- EXPECT_FLOAT_EQ(0.074074075, grads[4]);
- EXPECT_FLOAT_EQ(0, grads[5]);
- EXPECT_FLOAT_EQ(0.054398149, grads[6]);
- EXPECT_FLOAT_EQ(0, grads[7]);
-}
-TEST(AgradMixMatrixMdivideLeftTri, matrix_ffv_vector_ffv1_upper) {
- using stan::math::matrix_ffv;
- using stan::math::mdivide_left_tri;
- using stan::math::vector_ffv;
-
- matrix_f
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_right_ldlt_test.cpp:
> - EXPECT_THROW(mdivide_right_ldlt(rvd2, fv2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(rvd1, fv2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(vf1, fv2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(vd1, fv2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(rvf2, fd1), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(rvf1, fd1), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(vf2, fd1), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(rvf2, fd2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(rvf1, fd2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_ldlt(vf1, fd2), std::invalid_argument);
+TEST(MathMixMatFun, mdivideRightLdlt) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::mdivide_right_ldlt(x, stan::test::ldlt_factor(y));
+ };
+
+ Eigen::MatrixXd a(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_right_spd_test.cpp:
> - EXPECT_THROW(mdivide_right_spd(vf2, fd1), std::invalid_argument);
- EXPECT_THROW(mdivide_right_spd(rvf2, fd2), std::domain_error);
- EXPECT_THROW(mdivide_right_spd(rvf1, fd2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_spd(vf1, fd2), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, mdivideRightSpd) {
+ auto f = [](const auto& x, const auto& y) {
+ if (y.rows() != y.cols())
+ return stan::math::mdivide_right_spd(x, y);
+ auto y_sym = ((y + y.transpose()) * 0.5).eval(); // sym for finite diffs
+ return stan::math::mdivide_right_spd(x, y_sym);
+ };
+
+ // signature 1 of 2: matrix / matrix
+ Eigen::MatrixXd aa(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_right_test.cpp:
> - EXPECT_THROW(mdivide_right(vf1, fv2), std::invalid_argument);
- EXPECT_THROW(mdivide_right(vf2, fv2), std::invalid_argument);
- EXPECT_THROW(mdivide_right(rvf2, fd1), std::invalid_argument);
- EXPECT_THROW(mdivide_right(vf1, fd1), std::invalid_argument);
- EXPECT_THROW(mdivide_right(vf2, fd1), std::invalid_argument);
- EXPECT_THROW(mdivide_right(rvf1, fd2), std::invalid_argument);
- EXPECT_THROW(mdivide_right(vf1, fd2), std::invalid_argument);
- EXPECT_THROW(mdivide_right(vf2, fd2), std::invalid_argument);
+#include <vector>
+
+TEST(MathMixMatFun, mdivideRight) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::mdivide_right(x, y);
+ };
+
+ Eigen::MatrixXd a(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_right_tri_low_test.cpp:
> - vm2.setZero();
-
- EXPECT_THROW(mdivide_right_tri_low(fvm1, fvm2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_tri_low(fvm1, vm2), std::invalid_argument);
- EXPECT_THROW(mdivide_right_tri_low(vm1, fvm2), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+#include <limits>
+
+TEST(MathMixMatFun, mdivideRightTriLow) {
+ auto f = [](const auto& x, const auto& y) {
+ // no need to symmetrize becuase only uses view
+ return stan::math::mdivide_right_tri_low(x, y);
+ };
+
+ // signature 1 of 2: matrix / matrix
+ Eigen::MatrixXd aa(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/mdivide_right_tri_test.cpp:
> - Av(1, 0).d_.val_ = 1.0;
- Av(1, 1).d_.val_ = 1.0;
- Ad << 2.0, 3.0;
- Ad(0).d_.val_ = 1.0;
- Ad(1).d_.val_ = 1.0;
-
- I = mdivide_right_tri<Eigen::Upper>(Ad, Av);
- EXPECT_FLOAT_EQ(0.66666666, I(0).val_.val_.val());
- EXPECT_FLOAT_EQ(0.58333333, I(1).val_.val_.val());
- EXPECT_FLOAT_EQ(0.11111111, I(0).d_.val_.val());
- EXPECT_FLOAT_EQ(-0.090277776, I(1).d_.val_.val());
-
- std::vector<var> vars;
- vars.push_back(Av(0, 0).val_.val_);
- vars.push_back(Av(0, 1).val_.val_);
- vars.push_back(Av(1,
Zero-sized input test?
In test/unit/math/mix/mat/fun/multiply_test.cpp:
> @@ -0,0 +1,87 @@
+#include <test/unit/math/test_ad.hpp>
+
+TEST(mathMixMatFun, multiply) {
+ auto f
+ = [](const auto& x, const auto& y) { return stan::math::multiply(x, y); };
+
+ stan::test::ad_tolerances tols;
+ tols.hessian_hessian_ = 1e-1;
+ tols.hessian_fvar_hessian_ = 1e-1;
+
+ double a = 10;
+ Eigen::VectorXd v1(1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/rows_dot_product_test.cpp:
> - EXPECT_THROW(rows_dot_product(d2, v1), std::invalid_argument);
- EXPECT_THROW(rows_dot_product(d2, v2), std::invalid_argument);
- EXPECT_THROW(rows_dot_product(d2, v5), std::invalid_argument);
- EXPECT_THROW(rows_dot_product(d2, v6), std::invalid_argument);
-
- EXPECT_THROW(rows_dot_product(d3, v1), std::invalid_argument);
- EXPECT_THROW(rows_dot_product(d3, v2), std::invalid_argument);
- EXPECT_THROW(rows_dot_product(d3, v3), std::invalid_argument);
- EXPECT_THROW(rows_dot_product(d3, v4), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, rowsDotProduct) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::rows_dot_product(x, y);
+ };
+ Eigen::VectorXd u3(3);
Zero-sized input test?
In test/unit/math/mix/mat/fun/rows_dot_self_test.cpp:
>
- Eigen::Matrix<fvar<double>, Eigen::Dynamic, Eigen::Dynamic> m1(1, 1);
- m1 << 2.0;
- m1(0).d_ = 1.0;
- EXPECT_NEAR(4.0, rows_dot_self(m1)(0, 0).val_, 1E-12);
- EXPECT_NEAR(4.0, rows_dot_self(m1)(0, 0).d_, 1E-12);
+ Eigen::MatrixXd a11(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/singular_values_test.cpp:
>
- using stan::math::singular_values;
+ Eigen::MatrixXd m11(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/sub_col_test.cpp:
> - using stan::math::sub_col;
- stan::math::matrix_ffv m(3, 4);
- for (int i = 0; i < 3; ++i)
- for (int j = 0; j < 4; ++j) {
- m(i, j) = (i + 1) * (j + 1);
- m(i, j).d_ = 1.0;
- }
- stan::math::row_vector_ffv v = sub_col(m, 1, 2, 2);
- EXPECT_EQ(2, v.size());
- for (int i = 0; i < 2; ++i) {
- EXPECT_FLOAT_EQ(m(0 + i, 1).val_.val_.val(), v(i).val_.val_.val());
- EXPECT_FLOAT_EQ(m(0 + i, 1).d_.val_.val(), v(i).d_.val_.val());
- }
+
+TEST(MathMixMatFun, subCol) {
+ Eigen::MatrixXd a(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/sub_row_test.cpp:
> - using stan::math::sub_row;
- stan::math::matrix_ffv m(3, 4);
- for (int i = 0; i < 3; ++i)
- for (int j = 0; j < 4; ++j) {
- m(i, j) = (i + 1) * (j + 1);
- m(i, j).d_ = 1.0;
- }
- stan::math::row_vector_ffv v = sub_row(m, 1, 2, 2);
- EXPECT_EQ(2, v.size());
- for (int i = 0; i < 2; ++i) {
- EXPECT_FLOAT_EQ(m(0, 1 + i).val_.val_.val(), v(i).val_.val_.val());
- EXPECT_FLOAT_EQ(m(0, 1 + i).d_.val_.val(), v(i).d_.val_.val());
- }
+
+TEST(MathMixMatFun, subRow) {
+ Eigen::MatrixXd a(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/subtract_test.cpp:
> @@ -0,0 +1,89 @@
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, subtract) {
+ auto f
+ = [](const auto& x, const auto& y) { return stan::math::subtract(x, y); };
+
+ double d = 2;
+ Eigen::MatrixXd m11(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/trace_inv_quad_form_ldlt_test.cpp:
> - EXPECT_THROW(trace_inv_quad_form_ldlt(fv2, vd1), std::invalid_argument);
- EXPECT_THROW(trace_inv_quad_form_ldlt(fd1, rvf2), std::invalid_argument);
- EXPECT_THROW(trace_inv_quad_form_ldlt(fd1, rvf1), std::invalid_argument);
- EXPECT_THROW(trace_inv_quad_form_ldlt(fd1, vf2), std::invalid_argument);
- EXPECT_THROW(trace_inv_quad_form_ldlt(fd2, rvf2), std::invalid_argument);
- EXPECT_THROW(trace_inv_quad_form_ldlt(fd2, rvf1), std::invalid_argument);
- EXPECT_THROW(trace_inv_quad_form_ldlt(fd2, vf1), std::invalid_argument);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, traceInvQuadFormLdlt) {
+ auto f = [](const auto& x, const auto& y) {
+ auto x_ldlt = stan::test::ldlt_factor(x);
+ return stan::math::trace_inv_quad_form_ldlt(x_ldlt, y);
+ };
+
+ Eigen::MatrixXd a11(1, 1);
Zero-sized input test?
In test/unit/math/mix/mat/fun/trace_quad_form_test.cpp:
> - EXPECT_FLOAT_EQ(16, h[16]);
- EXPECT_FLOAT_EQ(16, h[17]);
- EXPECT_FLOAT_EQ(16, h[18]);
- EXPECT_FLOAT_EQ(16, h[19]);
- EXPECT_FLOAT_EQ(16, h[20]);
- EXPECT_FLOAT_EQ(16, h[21]);
- EXPECT_FLOAT_EQ(16, h[22]);
- EXPECT_FLOAT_EQ(16, h[23]);
+#include <test/unit/math/test_ad.hpp>
+
+TEST(MathMixMatFun, traceQuadForm) {
+ auto f = [](const auto& x, const auto& y) {
+ return stan::math::trace_quad_form(x, y);
+ };
+
+ Eigen::MatrixXd a11(1, 1);
Zero-sized input test?
In test/unit/math/mix/scal/fun/lb_constrain_test.cpp:
> @@ -0,0 +1,35 @@
+#include <test/unit/math/test_ad.hpp>
+#include <limits>
+
+template <typename T, typename U>
+typename boost::math::tools::promote_args<T, U>::type g1(const T& x,
It might be better to just use the Stan Math type trait return_type_t here.
return_type_t<T,U> g1(const T& x,...
Same goes for the other two uses of promote_args in this file.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
|
Yeah, the boundaries should be done with separate PRs. I will approve once the promote_args are changed. |
|
This is ready to be reviewed again when tests pass. I didn't mean to start reviews, but don't know how to get rid of all the junk in GitHub. Sorry about that. I resolved all the issues raised by @rok-cesnovar either by adding boundary condition tests or submitting a new issue for Stan math for ones that aren't consistent. |
|
(stat_comp_benchmarks/benchmarks/gp_pois_regr/gp_pois_regr.stan, 1.01) |
rok-cesnovar
left a comment
There was a problem hiding this comment.
Looks great!
Thank you very much for creating all those issues.
Summary
This improves test coverage by converting all real-valued functions of two or fewer arguments to the autodiff test framework. The full list is in issue #1412. Many of these did not have one or more of reverse, forward, or mixed mode tests and many more had poor coverage of types or boundary conditions.
This PR also adds convenience methods to the autodiff test framework in
test/unit/math/test_ad.hppfor converting among types and testing exceptions.Tests
Old test inputs were used for new tests. New tests were generated for boundary condition sizes and to cover all types. Each new test runs at each level of autodiff.
The tests in
mixhave complete coverage, so those infwdandrevwere removed.Side Effects
No.
Checklist
Math issue #(issue number)
Copyright holder: (fill in copyright holder information)
Columbia University
the basic tests are passing
./runTests.py test/unit)make test-headers)make doxygen)make cpplint)the code is written in idiomatic C++ and changes are documented in the doxygen
the new changes are tested