Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions src/stan/io/deserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class deserializer {
return map_vector_t(nullptr, m);
} else {
check_r_capacity(m);
stan::math::check_nonnegative("read", "size", m);
return map_vector_t(&scalar_ptr_increment(m), m);
}
}
Expand All @@ -195,6 +196,7 @@ class deserializer {
if (unlikely(m == 0)) {
return Ret(map_vector_t(nullptr, m));
} else {
stan::math::check_nonnegative("read", "size", m);
check_r_capacity(2 * m);
Ret ret(m);
for (Eigen::Index i = 0; i < m; ++i) {
Expand All @@ -217,6 +219,7 @@ class deserializer {
if (unlikely(m == 0)) {
return map_row_vector_t(nullptr, m);
} else {
stan::math::check_nonnegative("read", "size", m);
check_r_capacity(m);
return map_row_vector_t(&scalar_ptr_increment(m), m);
}
Expand All @@ -233,6 +236,7 @@ class deserializer {
if (unlikely(m == 0)) {
return Ret(map_row_vector_t(nullptr, m));
} else {
stan::math::check_nonnegative("read", "size", m);
check_r_capacity(2 * m);
Ret ret(m);
for (Eigen::Index i = 0; i < m; ++i) {
Expand All @@ -256,6 +260,8 @@ class deserializer {
if (rows == 0 || cols == 0) {
return map_matrix_t(nullptr, rows, cols);
} else {
stan::math::check_nonnegative("read", "rows", rows);
stan::math::check_nonnegative("read", "cols", cols);
check_r_capacity(rows * cols);
return map_matrix_t(&scalar_ptr_increment(rows * cols), rows, cols);
}
Expand All @@ -273,6 +279,8 @@ class deserializer {
if (rows == 0 || cols == 0) {
return Ret(map_matrix_t(nullptr, rows, cols));
} else {
stan::math::check_nonnegative("read", "rows", rows);
stan::math::check_nonnegative("read", "cols", cols);
check_r_capacity(2 * rows * cols);
Ret ret(rows, cols);
for (Eigen::Index i = 0; i < rows * cols; ++i) {
Expand Down Expand Up @@ -798,10 +806,12 @@ class deserializer {
require_matrix_t<Ret>* = nullptr>
inline auto read_constrain_cholesky_factor_cov(LP& lp, Eigen::Index M,
Eigen::Index N) {
stan::math::check_greater_or_equal("read_constrain_cholesky_factor_cov",
"M", M, N);
const Eigen::Index size
= (M == 0 || N == 0) ? 0 : (N * (N + 1)) / 2 + (M - N) * N;
return stan::math::cholesky_factor_constrain<Jacobian>(
this->read<conditional_var_val_t<Ret, vector_t>>((N * (N + 1)) / 2
+ (M - N) * N),
M, N, lp);
this->read<conditional_var_val_t<Ret, vector_t>>(size), M, N, lp);
}

/**
Expand Down Expand Up @@ -857,9 +867,10 @@ class deserializer {
template <typename Ret, bool Jacobian, typename LP,
require_matrix_t<Ret>* = nullptr>
inline auto read_constrain_cholesky_factor_corr(LP& lp, Eigen::Index K) {
// If K is 0, we want to read 0 elements to form a 0x0 matrix
const Eigen::Index size = (K == 0) ? 0 : (K * (K - 1)) / 2;
return stan::math::cholesky_corr_constrain<Jacobian>(
this->read<conditional_var_val_t<Ret, vector_t>>((K * (K - 1)) / 2), K,
lp);
this->read<conditional_var_val_t<Ret, vector_t>>(size), K, lp);
}

/**
Expand Down Expand Up @@ -914,9 +925,9 @@ class deserializer {
template <typename Ret, bool Jacobian, typename LP,
require_matrix_t<Ret>* = nullptr>
inline auto read_constrain_cov_matrix(LP& lp, Eigen::Index k) {
const Eigen::Index size = (k == 0) ? 0 : (k * (k - 1)) / 2;
return stan::math::cov_matrix_constrain<Jacobian>(
this->read<conditional_var_val_t<Ret, vector_t>>(k + (k * (k - 1)) / 2),
k, lp);
this->read<conditional_var_val_t<Ret, vector_t>>(k + size), k, lp);
}

/**
Expand Down Expand Up @@ -969,9 +980,9 @@ class deserializer {
require_not_std_vector_t<Ret>* = nullptr,
require_matrix_t<Ret>* = nullptr>
inline auto read_constrain_corr_matrix(LP& lp, Eigen::Index k) {
const Eigen::Index size = (k == 0) ? 0 : (k * (k - 1)) / 2;
return stan::math::corr_matrix_constrain<Jacobian>(
this->read<conditional_var_val_t<Ret, vector_t>>((k * (k - 1)) / 2), k,
lp);
this->read<conditional_var_val_t<Ret, vector_t>>(size), k, lp);
}

/**
Expand Down Expand Up @@ -1024,6 +1035,7 @@ class deserializer {
require_matrix_t<Ret>* = nullptr>
inline auto read_constrain_stochastic_column(LP& lp, Eigen::Index rows,
Eigen::Index cols) {
stan::math::check_positive("read_stochastic_column", "rows", rows);
return stan::math::stochastic_column_constrain<Jacobian>(
this->read<conditional_var_val_t<Ret, matrix_t>>(rows - 1, cols), lp);
}
Expand Down Expand Up @@ -1080,6 +1092,7 @@ class deserializer {
require_matrix_t<Ret>* = nullptr>
inline auto read_constrain_stochastic_row(LP& lp, Eigen::Index rows,
Eigen::Index cols) {
stan::math::check_positive("read_stochastic_row", "cols", cols);
return stan::math::stochastic_row_constrain<Jacobian>(
this->read<conditional_var_val_t<Ret, matrix_t>>(rows, cols - 1), lp);
}
Expand Down
36 changes: 36 additions & 0 deletions src/test/unit/io/deserializer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ TEST(deserializer_vector, read) {

double z = deserializer.read<double>();
EXPECT_FLOAT_EQ(11.0, z);
EXPECT_THROW(deserializer.read<Eigen::VectorXd>(-1), std::domain_error);
}

TEST(deserializer_vector, complex_read) {
Expand Down Expand Up @@ -100,6 +101,7 @@ TEST(deserializer_vector, complex_read) {

double z = deserializer.read<double>();
EXPECT_FLOAT_EQ(15.0, z);
EXPECT_THROW(deserializer.read<complex_vec>(-1), std::domain_error);
}

// row vector
Expand All @@ -126,6 +128,7 @@ TEST(deserializer_row_vector, read) {

double z = deserializer.read<double>();
EXPECT_FLOAT_EQ(11.0, z);
EXPECT_THROW(deserializer.read<Eigen::RowVectorXd>(-1), std::domain_error);
}

TEST(deserializer_row_vector, complex_read) {
Expand Down Expand Up @@ -154,6 +157,7 @@ TEST(deserializer_row_vector, complex_read) {

double z = deserializer.read<double>();
EXPECT_FLOAT_EQ(15.0, z);
EXPECT_THROW(deserializer.read<complex_row_vec>(-1), std::domain_error);
}

// matrix
Expand Down Expand Up @@ -181,6 +185,8 @@ TEST(deserializer_matrix, read) {

double a = deserializer.read<double>();
EXPECT_FLOAT_EQ(13.0, a);
EXPECT_THROW(deserializer.read<eig_mat>(-1, 1), std::domain_error);
EXPECT_THROW(deserializer.read<eig_mat>(1, -1), std::domain_error);
}

TEST(deserializer_matrix, complex_read) {
Expand All @@ -205,6 +211,8 @@ TEST(deserializer_matrix, complex_read) {
EXPECT_FLOAT_EQ(sentinal, y(i).imag());
sentinal++;
}
EXPECT_THROW(deserializer.read<eig_mat>(-1, 1), std::domain_error);
EXPECT_THROW(deserializer.read<eig_mat>(1, -1), std::domain_error);
}

// array
Expand Down Expand Up @@ -643,6 +651,9 @@ TEST(deserializer_vector, simplex_constrain) {
double lp = 0;
Eigen::VectorXd reference
= stan::math::simplex_constrain(stan::math::to_vector(theta));
EXPECT_THROW(
(deserializer.read_constrain_simplex<Eigen::VectorXd, false>(lp, 0)),
std::domain_error);
Eigen::VectorXd phi(
deserializer.read_constrain_simplex<Eigen::VectorXd, false>(
lp, theta.size() + 1));
Expand Down Expand Up @@ -683,6 +694,9 @@ TEST(deserializer_vector, sum_to_zero_constrain) {
theta.push_back(0.0);
stan::io::deserializer<double> deserializer(theta, theta_i);
double lp = 0;
EXPECT_THROW(
(deserializer.read_constrain_sum_to_zero<Eigen::VectorXd, false>(lp, 0)),
std::domain_error);
Eigen::VectorXd reference
= stan::math::sum_to_zero_constrain(stan::math::to_vector(theta));
Eigen::VectorXd phi(
Expand Down Expand Up @@ -723,6 +737,12 @@ TEST(deserializer_matrix, sum_to_zero_constrain) {
theta.push_back(0.0);
stan::io::deserializer<double> deserializer(theta, theta_i);
double lp = 0.0;
EXPECT_THROW((deserializer.read_constrain_sum_to_zero<Eigen::MatrixXd, false>(
lp, 0, 1)),
std::domain_error);
EXPECT_THROW((deserializer.read_constrain_sum_to_zero<Eigen::MatrixXd, false>(
lp, 1, 0)),
std::domain_error);
Eigen::MatrixXd reference
= stan::math::sum_to_zero_constrain(stan::math::to_matrix(theta, 2, 2));
Eigen::MatrixXd phi(
Expand Down Expand Up @@ -874,6 +894,13 @@ TEST(deserializer_matrix, cholesky_factor_cov_constrain) {
theta.push_back(-static_cast<double>(i));
stan::io::deserializer<double> deserializer(theta, theta_i);
double lp = 0;
EXPECT_THROW(
(deserializer.read_constrain_cholesky_factor_cov<Eigen::MatrixXd, false>(
lp, 0, 1)),
std::domain_error);
EXPECT_NO_THROW(
(deserializer.read_constrain_cholesky_factor_cov<Eigen::MatrixXd, false>(
lp, 0, 0)));
Eigen::MatrixXd reference = stan::math::cholesky_factor_constrain(
stan::math::to_vector(theta).segment(0, 6), 3, 3);
Eigen::MatrixXd L(
Expand Down Expand Up @@ -956,6 +983,9 @@ TEST(deserializer_matrix, cholesky_factor_corr_constrain) {
theta.push_back(-static_cast<double>(i));
stan::io::deserializer<double> deserializer(theta, theta_i);
double lp = 0;
EXPECT_NO_THROW(
(deserializer.read_constrain_cholesky_factor_corr<Eigen::MatrixXd, false>(
lp, 0)));
Eigen::MatrixXd reference = stan::math::cholesky_corr_constrain(
stan::math::to_vector(theta).segment(0, 3), 3);
Eigen::MatrixXd L(
Expand Down Expand Up @@ -1002,6 +1032,8 @@ TEST(deserializer_matrix, cov_matrix_constrain) {
theta.push_back(-static_cast<double>(i));
stan::io::deserializer<double> deserializer(theta, theta_i);
double lp = 0;
EXPECT_NO_THROW(
(deserializer.read_constrain_cov_matrix<Eigen::MatrixXd, false>(lp, 0)));
Eigen::MatrixXd reference = stan::math::cov_matrix_constrain(
stan::math::to_vector(theta).segment(0, 6), 3);
Eigen::MatrixXd L(
Expand Down Expand Up @@ -1042,6 +1074,8 @@ TEST(deserializer_matrix, corr_matrix_constrain) {
theta.push_back(-static_cast<double>(i));
stan::io::deserializer<double> deserializer(theta, theta_i);
double lp = 0;
EXPECT_NO_THROW(
(deserializer.read_constrain_corr_matrix<Eigen::MatrixXd, false>(lp, 0)));
Eigen::MatrixXd reference = stan::math::corr_matrix_constrain(
stan::math::to_vector(theta).segment(0, 3), 3);
Eigen::MatrixXd L(
Expand All @@ -1061,6 +1095,8 @@ TEST(deserializer_matrix, corr_matrix_jacobian) {
stan::io::deserializer<double> deserializer(theta, theta_i);
double lp_ref = 0.0;
double lp = 0.0;
EXPECT_NO_THROW(
(deserializer.read_constrain_corr_matrix<Eigen::MatrixXd, true>(lp, 0)));
Eigen::MatrixXd reference = stan::math::corr_matrix_constrain(
stan::math::to_vector(theta).segment(0, 3), 3, lp_ref);
Eigen::MatrixXd L(
Expand Down