diff --git a/stan/math/prim/fun/promote_scalar.hpp b/stan/math/prim/fun/promote_scalar.hpp index e75196e01da..ee7ab2abc2d 100644 --- a/stan/math/prim/fun/promote_scalar.hpp +++ b/stan/math/prim/fun/promote_scalar.hpp @@ -59,9 +59,11 @@ inline auto promote_scalar(UnPromotedType&& x) { // Forward decl for iterating over tuples used in std::vector template * = nullptr> + require_all_tuple_t* = nullptr, + require_not_same_t* = nullptr> inline constexpr promote_scalar_t promote_scalar(UnPromotedTypes&& x); + /** * Promote the scalar type of an standard vector to the requested type. * @@ -93,7 +95,8 @@ inline auto promote_scalar(UnPromotedType&& x) { * @param x input */ template *> + require_all_tuple_t*, + require_not_same_t*> inline constexpr promote_scalar_t promote_scalar(UnPromotedTypes&& x) { return index_apply>::value>( diff --git a/stan/math/prim/fun/stan_print.hpp b/stan/math/prim/fun/stan_print.hpp index 5d1b99330dd..b8d363b622f 100644 --- a/stan/math/prim/fun/stan_print.hpp +++ b/stan/math/prim/fun/stan_print.hpp @@ -52,6 +52,10 @@ void stan_print(std::ostream* o, const EigMat& x) { *o << ']'; } +// forward decl to allow the next two overloads to call each other +template * = nullptr> +void stan_print(std::ostream* o, const T& x); + template * = nullptr> void stan_print(std::ostream* o, const T& x) { *o << '['; @@ -64,7 +68,7 @@ void stan_print(std::ostream* o, const T& x) { *o << ']'; } -template * = nullptr> +template *> void stan_print(std::ostream* o, const T& x) { *o << '('; constexpr auto tuple_size = std::tuple_size>::value; diff --git a/stan/math/prim/prob/bernoulli_logit_glm_lpmf.hpp b/stan/math/prim/prob/bernoulli_logit_glm_lpmf.hpp index ffec07f2f8a..cb6983ef400 100644 --- a/stan/math/prim/prob/bernoulli_logit_glm_lpmf.hpp +++ b/stan/math/prim/prob/bernoulli_logit_glm_lpmf.hpp @@ -8,10 +8,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include @@ -54,11 +55,16 @@ return_type_t bernoulli_logit_glm_lpmf( using Eigen::log1p; using Eigen::Matrix; using std::exp; + using std::isfinite; constexpr int T_x_rows = T_x::RowsAtCompileTime; + using T_xbeta_partials = partials_return_t; using T_partials_return = partials_return_t; using T_ytheta_tmp = typename std::conditional_t>; + using T_xbeta_tmp = + typename std::conditional_t>; using T_x_ref = ref_type_if_t::value, T_x>; using T_alpha_ref = ref_type_if_t::value, T_alpha>; using T_beta_ref = ref_type_if_t::value, T_beta>; @@ -86,11 +92,10 @@ return_type_t bernoulli_logit_glm_lpmf( T_alpha_ref alpha_ref = alpha; T_beta_ref beta_ref = beta; - const auto& y_val = value_of_rec(y_ref); - const auto& x_val - = to_ref_if::value>(value_of_rec(x_ref)); - const auto& alpha_val = value_of_rec(alpha_ref); - const auto& beta_val = value_of_rec(beta_ref); + const auto& y_val = value_of(y_ref); + const auto& x_val = to_ref_if::value>(value_of(x_ref)); + const auto& alpha_val = value_of(alpha_ref); + const auto& beta_val = value_of(beta_ref); const auto& y_val_vec = as_column_vector_or_scalar(y_val); const auto& alpha_val_vec = as_column_vector_or_scalar(alpha_val); @@ -103,7 +108,7 @@ return_type_t bernoulli_logit_glm_lpmf( Array ytheta(N_instances); if (T_x_rows == 1) { T_ytheta_tmp ytheta_tmp - = forward_as((x_val * beta_val_vec)(0, 0)); + = forward_as((x_val * beta_val_vec)(0, 0)); ytheta = signs * (ytheta_tmp + as_array_or_scalar(alpha_val_vec)); } else { ytheta = (x_val * beta_val_vec).array(); @@ -120,7 +125,7 @@ return_type_t bernoulli_logit_glm_lpmf( .select(-exp_m_ytheta, (ytheta < -cutoff).select(ytheta, -log1p(exp_m_ytheta)))); - if (!std::isfinite(logp)) { + if (!isfinite(logp)) { check_finite(function, "Weight vector", beta); check_finite(function, "Intercept", alpha); check_finite(function, "Matrix of independent variables", ytheta); @@ -133,7 +138,7 @@ return_type_t bernoulli_logit_glm_lpmf( = (ytheta > cutoff) .select(-exp_m_ytheta, (ytheta < -cutoff) - .select(signs, + .select(signs * T_partials_return(1.0), signs * exp_m_ytheta / (exp_m_ytheta + 1))); if (!is_constant_all::value) { if (T_x_rows == 1) { diff --git a/stan/math/prim/prob/categorical_logit_glm_lpmf.hpp b/stan/math/prim/prob/categorical_logit_glm_lpmf.hpp index 04136e013d8..b327f910f7e 100644 --- a/stan/math/prim/prob/categorical_logit_glm_lpmf.hpp +++ b/stan/math/prim/prob/categorical_logit_glm_lpmf.hpp @@ -6,12 +6,13 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include #include @@ -50,11 +51,13 @@ return_type_t categorical_logit_glm_lpmf( using Eigen::Dynamic; using Eigen::Matrix; using std::exp; + using std::isfinite; using std::log; using T_y_ref = ref_type_t; using T_x_ref = ref_type_if_t::value, T_x>; using T_alpha_ref = ref_type_if_t::value, T_alpha>; using T_beta_ref = ref_type_if_t::value, T_beta>; + using T_beta_partials = partials_type_t>; constexpr int T_x_rows = T_x::RowsAtCompileTime; const size_t N_instances = T_x_rows == 1 ? stan::math::size(y) : x.rows(); @@ -82,11 +85,10 @@ return_type_t categorical_logit_glm_lpmf( T_alpha_ref alpha_ref = alpha; T_beta_ref beta_ref = beta; - const auto& x_val - = to_ref_if::value>(value_of_rec(x_ref)); - const auto& alpha_val = value_of_rec(alpha_ref); + const auto& x_val = to_ref_if::value>(value_of(x_ref)); + const auto& alpha_val = value_of(alpha_ref); const auto& beta_val - = to_ref_if::value>(value_of_rec(beta_ref)); + = to_ref_if::value>(value_of(beta_ref)); const auto& alpha_val_vec = as_column_vector_or_scalar(alpha_val).transpose(); @@ -117,7 +119,7 @@ return_type_t categorical_logit_glm_lpmf( // when we have newer Eigen T_partials_return logp = // lin(Eigen::all,y-1).sum() + log(inv_sum_exp_lin).sum() - lin_max.sum(); - if (!std::isfinite(logp)) { + if (!isfinite(logp)) { check_finite(function, "Weight vector", beta_ref); check_finite(function, "Intercept", alpha_ref); check_finite(function, "Matrix of independent variables", x_ref); @@ -128,7 +130,7 @@ return_type_t categorical_logit_glm_lpmf( if (!is_constant_all::value) { if (T_x_rows == 1) { - Array beta_y = beta_val.col(y_seq[0] - 1); + Array beta_y = beta_val.col(y_seq[0] - 1); for (int i = 1; i < N_instances; i++) { beta_y += beta_val.col(y_seq[i] - 1).array(); } @@ -137,7 +139,8 @@ return_type_t categorical_logit_glm_lpmf( - (exp_lin.matrix() * beta_val.transpose()).array().colwise() * inv_sum_exp_lin * N_instances; } else { - Array beta_y(N_instances, N_attributes); + Array beta_y(N_instances, + N_attributes); for (int i = 0; i < N_instances; i++) { beta_y.row(i) = beta_val.col(y_seq[i] - 1); } @@ -166,12 +169,11 @@ return_type_t categorical_logit_glm_lpmf( } } if (!is_constant_all::value) { - Matrix beta_derivative; + Matrix beta_derivative + = x_val.transpose().template cast() + * neg_softmax_lin.matrix(); if (T_x_rows == 1) { - beta_derivative - = x_val.transpose() * neg_softmax_lin.matrix() * N_instances; - } else { - beta_derivative = x_val.transpose() * neg_softmax_lin.matrix(); + beta_derivative *= N_instances; } for (int i = 0; i < N_instances; i++) { diff --git a/stan/math/prim/prob/neg_binomial_2_log_glm_lpmf.hpp b/stan/math/prim/prob/neg_binomial_2_log_glm_lpmf.hpp index 6b47f7be7c4..9c6c282296d 100644 --- a/stan/math/prim/prob/neg_binomial_2_log_glm_lpmf.hpp +++ b/stan/math/prim/prob/neg_binomial_2_log_glm_lpmf.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -72,6 +72,7 @@ return_type_t neg_binomial_2_log_glm_lpmf( using Eigen::log1p; using Eigen::Matrix; constexpr int T_x_rows = T_x::RowsAtCompileTime; + using T_xbeta_partials = partials_return_t; using T_partials_return = partials_return_t; using T_precision_val = typename std::conditional_t< @@ -85,6 +86,9 @@ return_type_t neg_binomial_2_log_glm_lpmf( using T_theta_tmp = typename std::conditional_t>; + using T_xbeta_tmp = + typename std::conditional_t>; using T_x_ref = ref_type_if_t::value, T_x>; using T_alpha_ref = ref_type_if_t::value, T_alpha>; using T_beta_ref = ref_type_if_t::value, T_beta>; @@ -103,8 +107,8 @@ return_type_t neg_binomial_2_log_glm_lpmf( check_consistent_size(function, "Vector of intercepts", alpha, N_instances); T_alpha_ref alpha_ref = alpha; T_beta_ref beta_ref = beta; - const auto& beta_val = value_of_rec(beta_ref); - const auto& alpha_val = value_of_rec(alpha_ref); + const auto& beta_val = value_of(beta_ref); + const auto& alpha_val = value_of(alpha_ref); const auto& beta_val_vec = to_ref(as_column_vector_or_scalar(beta_val)); const auto& alpha_val_vec = to_ref(as_column_vector_or_scalar(alpha_val)); check_finite(function, "Weight vector", beta_val_vec); @@ -117,8 +121,8 @@ return_type_t neg_binomial_2_log_glm_lpmf( const auto& y_ref = to_ref(y); T_phi_ref phi_ref = phi; - const auto& y_val = value_of_rec(y_ref); - const auto& phi_val = value_of_rec(phi_ref); + const auto& y_val = value_of(y_ref); + const auto& phi_val = value_of(phi_ref); const auto& y_val_vec = to_ref(as_column_vector_or_scalar(y_val)); const auto& phi_val_vec = to_ref(as_column_vector_or_scalar(phi_val)); @@ -131,8 +135,7 @@ return_type_t neg_binomial_2_log_glm_lpmf( T_x_ref x_ref = x; - const auto& x_val - = to_ref_if::value>(value_of_rec(x_ref)); + const auto& x_val = to_ref_if::value>(value_of(x_ref)); const auto& y_arr = as_array_or_scalar(y_val_vec); const auto& phi_arr = as_array_or_scalar(phi_val_vec); @@ -140,7 +143,7 @@ return_type_t neg_binomial_2_log_glm_lpmf( Array theta(N_instances); if (T_x_rows == 1) { T_theta_tmp theta_tmp - = forward_as((x_val * beta_val_vec)(0, 0)); + = forward_as((x_val * beta_val_vec)(0, 0)); theta = theta_tmp + as_array_or_scalar(alpha_val_vec); } else { theta = (x_val * beta_val_vec).array(); @@ -171,10 +174,11 @@ return_type_t neg_binomial_2_log_glm_lpmf( logp += multiply_log(phi_vec[n], phi_vec[n]) - lgamma(phi_vec[n]); } } else { + using T_phi_scalar = scalar_type_t; logp += N_instances - * (multiply_log(forward_as(phi_val), - forward_as(phi_val)) - - lgamma(forward_as(phi_val))); + * (multiply_log(forward_as(phi_val), + forward_as(phi_val)) + - lgamma(forward_as(phi_val))); } } logp -= sum(y_plus_phi * logsumexp_theta_logphi); diff --git a/stan/math/prim/prob/normal_id_glm_lpdf.hpp b/stan/math/prim/prob/normal_id_glm_lpdf.hpp index 7a510e4c765..c42ecdf5f7b 100644 --- a/stan/math/prim/prob/normal_id_glm_lpdf.hpp +++ b/stan/math/prim/prob/normal_id_glm_lpdf.hpp @@ -6,12 +6,13 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include @@ -59,6 +60,7 @@ return_type_t normal_id_glm_lpdf( using Eigen::Dynamic; using Eigen::Matrix; using Eigen::VectorXd; + using std::isfinite; constexpr int T_x_rows = T_x::RowsAtCompileTime; using T_partials_return = partials_return_t; @@ -86,7 +88,7 @@ return_type_t normal_id_glm_lpdf( N_instances); check_consistent_size(function, "Vector of intercepts", alpha, N_instances); T_sigma_ref sigma_ref = sigma; - const auto& sigma_val = value_of_rec(sigma_ref); + const auto& sigma_val = value_of(sigma_ref); const auto& sigma_val_vec = to_ref(as_column_vector_or_scalar(sigma_val)); check_positive_finite(function, "Scale vector", sigma_val_vec); @@ -102,11 +104,10 @@ return_type_t normal_id_glm_lpdf( T_alpha_ref alpha_ref = alpha; T_beta_ref beta_ref = beta; - const auto& y_val = value_of_rec(y_ref); - const auto& x_val - = to_ref_if::value>(value_of_rec(x_ref)); - const auto& alpha_val = value_of_rec(alpha_ref); - const auto& beta_val = value_of_rec(beta_ref); + const auto& y_val = value_of(y_ref); + const auto& x_val = to_ref_if::value>(value_of(x_ref)); + const auto& alpha_val = value_of(alpha_ref); + const auto& beta_val = value_of(beta_ref); const auto& y_val_vec = as_column_vector_or_scalar(y_val); const auto& alpha_val_vec = as_column_vector_or_scalar(alpha_val); @@ -116,7 +117,7 @@ return_type_t normal_id_glm_lpdf( T_scale_val inv_sigma = 1.0 / as_array_or_scalar(sigma_val_vec); // the most efficient way to calculate this depends on template parameters - double y_scaled_sq_sum; + T_partials_return y_scaled_sq_sum; Array y_scaled(N_instances); if (T_x_rows == 1) { @@ -178,7 +179,8 @@ return_type_t normal_id_glm_lpdf( } else { y_scaled_sq_sum = sum(y_scaled * y_scaled); partials<4>(ops_partials)[0] - = (y_scaled_sq_sum - N_instances) * forward_as(inv_sigma); + = (y_scaled_sq_sum - N_instances) + * forward_as>(inv_sigma); } } else { y_scaled_sq_sum = sum(y_scaled * y_scaled); @@ -187,7 +189,7 @@ return_type_t normal_id_glm_lpdf( y_scaled_sq_sum = sum(y_scaled * y_scaled); } - if (!std::isfinite(y_scaled_sq_sum)) { + if (!isfinite(y_scaled_sq_sum)) { check_finite(function, "Vector of dependent variables", y_val_vec); check_finite(function, "Weight vector", beta_val_vec); check_finite(function, "Intercept", alpha_val_vec); @@ -204,7 +206,8 @@ return_type_t normal_id_glm_lpdf( if (is_vector::value) { logp -= sum(log(sigma_val_vec)); } else { - logp -= N_instances * log(forward_as(sigma_val_vec)); + logp -= N_instances + * log(forward_as>(sigma_val_vec)); } } logp -= 0.5 * y_scaled_sq_sum; diff --git a/stan/math/prim/prob/ordered_logistic_glm_lpmf.hpp b/stan/math/prim/prob/ordered_logistic_glm_lpmf.hpp index d1c6113c590..e445762be28 100644 --- a/stan/math/prim/prob/ordered_logistic_glm_lpmf.hpp +++ b/stan/math/prim/prob/ordered_logistic_glm_lpmf.hpp @@ -6,12 +6,13 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include @@ -54,8 +55,12 @@ return_type_t ordered_logistic_glm_lpmf( using std::exp; using std::isfinite; constexpr int T_x_rows = T_x::RowsAtCompileTime; + using T_cuts_partials = partials_return_t; + using T_xbeta_partials = partials_return_t; using T_partials_return = partials_return_t; - typedef typename std::conditional_t + typedef typename std::conditional_t< + T_x_rows == 1, T_xbeta_partials, + Eigen::Matrix> T_location; using T_y_ref = ref_type_t; using T_x_ref = ref_type_if_t::value, T_x>; @@ -72,7 +77,7 @@ return_type_t ordered_logistic_glm_lpmf( check_consistent_size(function, "Weight vector", beta, N_attributes); T_y_ref y_ref = y; T_cuts_ref cuts_ref = cuts; - const auto& cuts_val = value_of_rec(cuts_ref); + const auto& cuts_val = value_of(cuts_ref); const auto& cuts_val_vec = to_ref(as_column_vector_or_scalar(cuts_val)); check_bounded(function, "Vector of dependent variables", y_ref, 1, N_classes); check_ordered(function, "Cut-points", cuts_val_vec); @@ -93,15 +98,14 @@ return_type_t ordered_logistic_glm_lpmf( T_x_ref x_ref = x; T_beta_ref beta_ref = beta; - const auto& x_val - = to_ref_if::value>(value_of_rec(x_ref)); - const auto& beta_val = value_of_rec(beta_ref); + const auto& x_val = to_ref_if::value>(value_of(x_ref)); + const auto& beta_val = value_of(beta_ref); const auto& beta_val_vec = to_ref_if::value>( as_column_vector_or_scalar(beta_val)); scalar_seq_view y_seq(y_ref); - Array cuts_y1(N_instances), cuts_y2(N_instances); + Array cuts_y1(N_instances), cuts_y2(N_instances); for (int i = 0; i < N_instances; i++) { int c = y_seq[i]; if (c != N_classes) { @@ -122,8 +126,10 @@ return_type_t ordered_logistic_glm_lpmf( check_finite(function, "Matrix of independent variables", x); } - Array cut2 = as_array_or_scalar(location) - cuts_y2; - Array cut1 = as_array_or_scalar(location) - cuts_y1; + Array cut2 + = as_array_or_scalar(location) - cuts_y2; + Array cut1 + = as_array_or_scalar(location) - cuts_y1; // Not immediately evaluating next two expressions benefits performance auto m_log_1p_exp_cut1 @@ -156,18 +162,18 @@ return_type_t ordered_logistic_glm_lpmf( auto ops_partials = make_partials_propagator(x_ref, beta_ref, cuts_ref); if (!is_constant_all::value) { - Array exp_m_cut1 = exp(-cut1); - Array exp_m_cut2 = exp(-cut2); - Array exp_cuts_diff = exp(cuts_y2 - cuts_y1); - Array d1 + Array exp_m_cut1 = exp(-cut1); + Array exp_m_cut2 = exp(-cut2); + Array exp_cuts_diff = exp(cuts_y2 - cuts_y1); + Array d1 = (cut2 > 0).select(exp_m_cut2 / (1 + exp_m_cut2), 1 / (1 + exp(cut2))) - exp_cuts_diff / (exp_cuts_diff - 1); - Array d2 + Array d2 = 1 / (1 - exp_cuts_diff) - (cut1 > 0).select(exp_m_cut1 / (1 + exp_m_cut1), 1 / (1 + exp(cut1))); if (!is_constant_all::value) { - Matrix location_derivative = d1 - d2; + Matrix location_derivative = d1 - d2; if (!is_constant_all::value) { if (T_x_rows == 1) { edge<0>(ops_partials).partials_ diff --git a/stan/math/prim/prob/poisson_log_glm_lpmf.hpp b/stan/math/prim/prob/poisson_log_glm_lpmf.hpp index 4cc0a7f2200..f28a2b6b380 100644 --- a/stan/math/prim/prob/poisson_log_glm_lpmf.hpp +++ b/stan/math/prim/prob/poisson_log_glm_lpmf.hpp @@ -7,11 +7,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include @@ -57,11 +58,16 @@ return_type_t poisson_log_glm_lpmf(const T_y& y, using Eigen::Dynamic; using Eigen::Matrix; using std::exp; + using std::isfinite; constexpr int T_x_rows = T_x::RowsAtCompileTime; + using T_xbeta_partials = partials_return_t; using T_partials_return = partials_return_t; using T_theta_tmp = typename std::conditional_t>; + using T_xbeta_tmp = + typename std::conditional_t>; using T_x_ref = ref_type_if_t::value, T_x>; using T_alpha_ref = ref_type_if_t::value, T_alpha>; using T_beta_ref = ref_type_if_t::value, T_beta>; @@ -88,11 +94,10 @@ return_type_t poisson_log_glm_lpmf(const T_y& y, T_alpha_ref alpha_ref = alpha; T_beta_ref beta_ref = beta; - const auto& y_val = value_of_rec(y_ref); - const auto& x_val - = to_ref_if::value>(value_of_rec(x_ref)); - const auto& alpha_val = value_of_rec(alpha_ref); - const auto& beta_val = value_of_rec(beta_ref); + const auto& y_val = value_of(y_ref); + const auto& x_val = to_ref_if::value>(value_of(x_ref)); + const auto& alpha_val = value_of(alpha_ref); + const auto& beta_val = value_of(beta_ref); const auto& y_val_vec = to_ref(as_column_vector_or_scalar(y_val)); const auto& alpha_val_vec = as_column_vector_or_scalar(alpha_val); @@ -102,7 +107,7 @@ return_type_t poisson_log_glm_lpmf(const T_y& y, Array theta(N_instances); if (T_x_rows == 1) { T_theta_tmp theta_tmp - = forward_as((x_val * beta_val_vec).coeff(0, 0)); + = forward_as((x_val * beta_val_vec).coeff(0, 0)); theta = theta_tmp + as_array_or_scalar(alpha_val_vec); } else { theta = x_val * beta_val_vec; @@ -111,8 +116,8 @@ return_type_t poisson_log_glm_lpmf(const T_y& y, Matrix theta_derivative = as_array_or_scalar(y_val_vec) - exp(theta.array()); - double theta_derivative_sum = sum(theta_derivative); - if (!std::isfinite(theta_derivative_sum)) { + T_partials_return theta_derivative_sum = sum(theta_derivative); + if (!isfinite(theta_derivative_sum)) { check_finite(function, "Weight vector", beta); check_finite(function, "Intercept", alpha); check_finite(function, "Matrix of independent variables", theta); @@ -120,11 +125,7 @@ return_type_t poisson_log_glm_lpmf(const T_y& y, T_partials_return logp(0); if (include_summand::value) { - if (is_vector::value) { - logp -= sum(lgamma(as_array_or_scalar(y_val_vec) + 1)); - } else { - logp -= lgamma(forward_as(y_val) + 1); - } + logp -= sum(lgamma(as_array_or_scalar(y_val_vec) + 1)); } logp += sum(as_array_or_scalar(y_val_vec) * theta.array() diff --git a/test/unit/math/mix/prob/bernoulli_logit_glm_lpmf_test.cpp b/test/unit/math/mix/prob/bernoulli_logit_glm_lpmf_test.cpp new file mode 100644 index 00000000000..430ff1a4769 --- /dev/null +++ b/test/unit/math/mix/prob/bernoulli_logit_glm_lpmf_test.cpp @@ -0,0 +1,25 @@ +#include +#include + +TEST(mathMixScalFun, bernoulli_logit_glm_lpmf) { + auto f = [](const auto y) { + return [=](const auto& x, const auto& alpha, const auto& beta) { + return stan::math::bernoulli_logit_glm_lpmf(y, x, alpha, beta); + }; + }; + + std::vector y{0, 1}; + Eigen::MatrixXd x = Eigen::MatrixXd::Random(2, 2); + Eigen::RowVectorXd x_rowvec = x.row(0); + Eigen::VectorXd alpha = Eigen::VectorXd::Random(2); + Eigen::VectorXd beta = Eigen::VectorXd::Random(2); + + stan::test::expect_ad(f(y[0]), x, alpha, beta); + stan::test::expect_ad(f(y[0]), x, alpha[0], beta); + stan::test::expect_ad(f(y[1]), x_rowvec, alpha, beta); + stan::test::expect_ad(f(y[1]), x_rowvec, alpha[0], beta); + stan::test::expect_ad(f(y), x, alpha, beta); + stan::test::expect_ad(f(y), x, alpha[0], beta); + stan::test::expect_ad(f(y), x_rowvec, alpha, beta); + stan::test::expect_ad(f(y), x_rowvec, alpha[0], beta); +} diff --git a/test/unit/math/mix/prob/categorical_logit_glm_lpmf_test.cpp b/test/unit/math/mix/prob/categorical_logit_glm_lpmf_test.cpp new file mode 100644 index 00000000000..084a92fc166 --- /dev/null +++ b/test/unit/math/mix/prob/categorical_logit_glm_lpmf_test.cpp @@ -0,0 +1,21 @@ +#include +#include + +TEST(mathMixScalFun, categorical_logit_glm_lpmf) { + auto f = [](const auto y) { + return [=](const auto& x, const auto& alpha, const auto& beta) { + return stan::math::categorical_logit_glm_lpmf(y, x, alpha, beta); + }; + }; + + std::vector y{0, 1}; + Eigen::MatrixXd x = Eigen::MatrixXd::Random(2, 2); + Eigen::RowVectorXd x_rowvec = x.row(0); + Eigen::VectorXd alpha = Eigen::VectorXd::Random(2); + Eigen::VectorXd beta = Eigen::VectorXd::Random(2); + + stan::test::expect_ad(f(y[0]), x, alpha, beta); + stan::test::expect_ad(f(y[1]), x_rowvec, alpha, beta); + stan::test::expect_ad(f(y), x, alpha, beta); + stan::test::expect_ad(f(y), x_rowvec, alpha, beta); +} diff --git a/test/unit/math/mix/prob/neg_binomial_2_log_glm_lpmf_test.cpp b/test/unit/math/mix/prob/neg_binomial_2_log_glm_lpmf_test.cpp new file mode 100644 index 00000000000..92d8e42754f --- /dev/null +++ b/test/unit/math/mix/prob/neg_binomial_2_log_glm_lpmf_test.cpp @@ -0,0 +1,32 @@ +#include +#include + +TEST(mathMixScalFun, neg_binomial_2_log_glm_lpmf) { + auto f = [](const auto y, const auto& x) { + return [=](const auto& alpha, const auto& beta, const auto& phi) { + return stan::math::neg_binomial_2_log_glm_lpmf(y, x, alpha, beta, phi); + }; + }; + auto f2 = [](const auto y, const auto& phi) { + return [=](const auto& x, const auto& alpha, const auto& beta) { + return stan::math::neg_binomial_2_log_glm_lpmf(y, x, alpha, beta, phi); + }; + }; + + std::vector y{0, 1}; + Eigen::MatrixXd x = Eigen::MatrixXd::Random(2, 2); + Eigen::RowVectorXd x_rowvec = x.row(0); + Eigen::VectorXd alpha = Eigen::VectorXd::Random(2); + Eigen::VectorXd beta = Eigen::VectorXd::Random(2); + double phi = 1.5; + + stan::test::expect_ad(f(y[0], x), alpha, beta, phi); + stan::test::expect_ad(f(y[0], x), alpha[0], beta, phi); + stan::test::expect_ad(f(y[0], x_rowvec), alpha, beta, phi); + stan::test::expect_ad(f(y[0], x_rowvec), alpha[0], beta, phi); + + stan::test::expect_ad(f2(y, phi), x, alpha, beta); + stan::test::expect_ad(f2(y, phi), x, alpha[0], beta); + stan::test::expect_ad(f2(y, phi), x_rowvec, alpha, beta); + stan::test::expect_ad(f2(y, phi), x_rowvec, alpha[0], beta); +} diff --git a/test/unit/math/mix/prob/normal_id_glm_lpdf_test.cpp b/test/unit/math/mix/prob/normal_id_glm_lpdf_test.cpp new file mode 100644 index 00000000000..3af9083a628 --- /dev/null +++ b/test/unit/math/mix/prob/normal_id_glm_lpdf_test.cpp @@ -0,0 +1,38 @@ +#include +#include + +TEST(mathMixScalFun, normal_id_glm_lpdf) { + auto f = [](const auto& y, const auto& x) { + return [=](const auto& alpha, const auto& beta, const auto& sigma) { + return stan::math::normal_id_glm_lpdf(y, x, alpha, beta, sigma); + }; + }; + auto f2 = [](const auto& beta, const auto& sigma) { + return [=](const auto& y, const auto& x, const auto& alpha) { + return stan::math::normal_id_glm_lpdf(y, x, alpha, beta, sigma); + }; + }; + + Eigen::VectorXd y = Eigen::VectorXd::Random(2); + Eigen::MatrixXd x = Eigen::MatrixXd::Random(2, 2); + Eigen::RowVectorXd x_rowvec = x.row(0); + Eigen::VectorXd alpha = Eigen::VectorXd::Random(2); + Eigen::VectorXd beta = Eigen::VectorXd::Random(2); + Eigen::VectorXd sigma = Eigen::VectorXd::Random(2); + + stan::test::expect_ad(f(y, x), alpha, beta, sigma); + stan::test::expect_ad(f(y, x), alpha[0], beta, sigma); + stan::test::expect_ad(f(y, x), alpha, beta, sigma[0]); + + stan::test::expect_ad(f(y, x_rowvec), alpha, beta, sigma); + stan::test::expect_ad(f(y, x_rowvec), alpha[0], beta, sigma); + stan::test::expect_ad(f(y, x_rowvec), alpha, beta, sigma[0]); + + stan::test::expect_ad(f2(beta, sigma), y, x, alpha); + stan::test::expect_ad(f2(beta, sigma[0]), y, x, alpha); + stan::test::expect_ad(f2(beta, sigma), y, x, alpha[0]); + + stan::test::expect_ad(f2(beta, sigma), y, x_rowvec, alpha); + stan::test::expect_ad(f2(beta, sigma[0]), y, x_rowvec, alpha); + stan::test::expect_ad(f2(beta, sigma), y, x_rowvec, alpha[0]); +} diff --git a/test/unit/math/mix/prob/ordered_logistic_glm_lpmf_test.cpp b/test/unit/math/mix/prob/ordered_logistic_glm_lpmf_test.cpp new file mode 100644 index 00000000000..db0a34f9d92 --- /dev/null +++ b/test/unit/math/mix/prob/ordered_logistic_glm_lpmf_test.cpp @@ -0,0 +1,21 @@ +#include +#include + +TEST(mathMixScalFun, ordered_logistic_glm_lpmf) { + auto f = [](const auto y) { + return [=](const auto& x, const auto& beta, const auto& cutpoints) { + return stan::math::ordered_logistic_glm_lpmf(y, x, beta, cutpoints); + }; + }; + + std::vector y{0, 1, 2}; + Eigen::MatrixXd x = Eigen::MatrixXd::Random(2, 2); + Eigen::RowVectorXd x_rowvec = x.row(0); + Eigen::VectorXd cutpoints = stan::math::sort_asc(Eigen::VectorXd::Random(2)); + Eigen::VectorXd beta = Eigen::VectorXd::Random(2); + + stan::test::expect_ad(f(y[0]), x, beta, cutpoints); + stan::test::expect_ad(f(y[0]), x_rowvec, beta, cutpoints); + stan::test::expect_ad(f(y), x, beta, cutpoints); + stan::test::expect_ad(f(y), x_rowvec, beta, cutpoints); +} diff --git a/test/unit/math/mix/prob/poisson_log_glm_lpmf_test.cpp b/test/unit/math/mix/prob/poisson_log_glm_lpmf_test.cpp new file mode 100644 index 00000000000..081b5816344 --- /dev/null +++ b/test/unit/math/mix/prob/poisson_log_glm_lpmf_test.cpp @@ -0,0 +1,28 @@ +#include +#include + +TEST(mathMixScalFun, poisson_log_glm_lpmf) { + auto f = [](const auto y) { + return [=](const auto& x, const auto& alpha, const auto& beta) { + return stan::math::poisson_log_glm_lpmf(y, x, alpha, beta); + }; + }; + + std::vector y{0, 1, 2}; + Eigen::MatrixXd x = Eigen::MatrixXd::Random(2, 2); + Eigen::RowVectorXd x_rowvec = x.row(0); + Eigen::VectorXd alpha = Eigen::VectorXd::Random(2); + Eigen::VectorXd beta = Eigen::VectorXd::Random(2); + + stan::test::expect_ad(f(y[0]), x, alpha, beta); + stan::test::expect_ad(f(y[0]), x, alpha[0], beta); + + stan::test::expect_ad(f(y[0]), x_rowvec, alpha, beta); + stan::test::expect_ad(f(y[0]), x_rowvec, alpha[0], beta); + + stan::test::expect_ad(f(y), x, alpha, beta); + stan::test::expect_ad(f(y), x, alpha[0], beta); + + stan::test::expect_ad(f(y), x_rowvec, alpha, beta); + stan::test::expect_ad(f(y), x_rowvec, alpha[0], beta); +} diff --git a/test/unit/math/prim/fun/stan_print_test.cpp b/test/unit/math/prim/fun/stan_print_test.cpp index f7b6fcee487..53cb6ec4cb4 100644 --- a/test/unit/math/prim/fun/stan_print_test.cpp +++ b/test/unit/math/prim/fun/stan_print_test.cpp @@ -11,6 +11,9 @@ TEST(MathPrim, basic_print) { std::tuple> tup(v, i, a); + std::vector>> arr_tup{ + tup, tup}; + { std::stringstream s; stan::math::stan_print(&s, i); @@ -52,6 +55,11 @@ TEST(MathPrim, basic_print) { stan::math::stan_print(&s, tup); EXPECT_TRUE(s.str().find("([1],1,[1])") != std::string::npos); } + { + std::stringstream s; + stan::math::stan_print(&s, arr_tup); + EXPECT_TRUE(s.str().find("[([1],1,[1])") != std::string::npos); + } } TEST(MathPrim, basic_expressions) {