diff --git a/stan/math/fwd/fun/inv_logit.hpp b/stan/math/fwd/fun/inv_logit.hpp index 7becb85444a..325a74a133a 100644 --- a/stan/math/fwd/fun/inv_logit.hpp +++ b/stan/math/fwd/fun/inv_logit.hpp @@ -16,10 +16,10 @@ namespace math { * @param x argument * @return inverse logit of argument */ -template -inline fvar inv_logit(const fvar& x) { - return fvar(inv_logit(x.val_), - x.d_ * inv_logit(x.val_) * (1 - inv_logit(x.val_))); +template * = nullptr> +inline auto inv_logit(T&& x) { + return std::decay_t(inv_logit(x.val_), + x.d_ * inv_logit(x.val_) * (1 - inv_logit(x.val_))); } } // namespace math diff --git a/stan/math/fwd/fun/log_softmax.hpp b/stan/math/fwd/fun/log_softmax.hpp index 82d1f7b0204..8e52ebb0fdd 100644 --- a/stan/math/fwd/fun/log_softmax.hpp +++ b/stan/math/fwd/fun/log_softmax.hpp @@ -19,36 +19,38 @@ namespace math { * @throw std::domain_error If the input vector is size 0. */ template * = nullptr> -inline auto log_softmax(const T& x) { - return apply_vector_unary::apply(x, [&](const auto& alpha) { - using T_alpha = decltype(alpha); - using T_fvar = value_type_t; - using T_fvar_inner = typename T_fvar::Scalar; - - const Eigen::Ref>& alpha_ref = alpha; - Eigen::Matrix alpha_t = alpha_ref.val(); - Eigen::Matrix softmax_alpha_t = softmax(alpha_t); - - Eigen::Matrix log_softmax_alpha(alpha.size()); - log_softmax_alpha.val() = log_softmax(alpha_t); - log_softmax_alpha.d().setZero(); - - for (int m = 0; m < alpha.size(); ++m) { - T_fvar_inner negative_alpha_m_d_times_softmax_alpha_t_m - = -alpha_ref.coeff(m).d_ * softmax_alpha_t(m); - for (int k = 0; k < alpha.size(); ++k) { - if (m == k) { - log_softmax_alpha(k).d_ - += alpha_ref.coeff(m).d_ - + negative_alpha_m_d_times_softmax_alpha_t_m; - } else { - log_softmax_alpha(k).d_ += negative_alpha_m_d_times_softmax_alpha_t_m; +inline auto log_softmax(T&& x) { + return apply_vector_unary::apply( + std::forward(x), [&](const auto& alpha) { + using T_alpha = decltype(alpha); + using T_fvar = value_type_t; + using T_fvar_inner = typename T_fvar::Scalar; + + const Eigen::Ref>& alpha_ref = alpha; + Eigen::Matrix alpha_t = alpha_ref.val(); + Eigen::Matrix softmax_alpha_t = softmax(alpha_t); + + Eigen::Matrix log_softmax_alpha(alpha.size()); + log_softmax_alpha.val() = log_softmax(alpha_t); + log_softmax_alpha.d().setZero(); + + for (int m = 0; m < alpha.size(); ++m) { + T_fvar_inner negative_alpha_m_d_times_softmax_alpha_t_m + = -alpha_ref.coeff(m).d_ * softmax_alpha_t(m); + for (int k = 0; k < alpha.size(); ++k) { + if (m == k) { + log_softmax_alpha(k).d_ + += alpha_ref.coeff(m).d_ + + negative_alpha_m_d_times_softmax_alpha_t_m; + } else { + log_softmax_alpha(k).d_ + += negative_alpha_m_d_times_softmax_alpha_t_m; + } + } } - } - } - return log_softmax_alpha; - }); + return log_softmax_alpha; + }); } } // namespace math diff --git a/stan/math/fwd/fun/log_sum_exp.hpp b/stan/math/fwd/fun/log_sum_exp.hpp index 30795b8f99b..cf61b472cc8 100644 --- a/stan/math/fwd/fun/log_sum_exp.hpp +++ b/stan/math/fwd/fun/log_sum_exp.hpp @@ -50,9 +50,9 @@ inline fvar log_sum_exp(const fvar& x1, double x2) { * @return The log of the sum of the exponentiated vector values. */ template * = nullptr> -inline auto log_sum_exp(const T& x) { +inline auto log_sum_exp(T&& x) { return apply_vector_unary>::reduce( - to_ref(x), [&](const auto& v) { + to_ref(std::forward(x)), [&](const auto& v) { using T_fvar_inner = typename value_type_t::Scalar; using mat_type = Eigen::Matrix; mat_type vals = v.val(); diff --git a/stan/math/fwd/fun/norm1.hpp b/stan/math/fwd/fun/norm1.hpp index 151216f2f12..89a9ebb4de3 100644 --- a/stan/math/fwd/fun/norm1.hpp +++ b/stan/math/fwd/fun/norm1.hpp @@ -15,14 +15,14 @@ namespace math { /** * Compute the L1 norm of the specified vector of values. * - * @tparam T Type of input vector. + * @tparam Container Type of input vector. * @param[in] x Vector of specified values. * @return L1 norm of x. */ template * = nullptr> -inline auto norm1(const Container& x) { +inline auto norm1(Container&& x) { return apply_vector_unary>::reduce( - to_ref(x), [&](const auto& v) { + to_ref(std::forward(x)), [&](const auto& v) { using T_fvar_inner = typename value_type_t::Scalar; return fvar(norm1(v.val()), v.d().cwiseProduct(sign(v.val())).sum()); diff --git a/stan/math/fwd/fun/norm2.hpp b/stan/math/fwd/fun/norm2.hpp index 3ba8200363a..73aa90ed022 100644 --- a/stan/math/fwd/fun/norm2.hpp +++ b/stan/math/fwd/fun/norm2.hpp @@ -14,14 +14,14 @@ namespace math { /** * Compute the L2 norm of the specified vector of values. * - * @tparam T Type of input vector. + * @tparam Container Type of input vector. * @param[in] x Vector of specified values. * @return L2 norm of x. */ template * = nullptr> -inline auto norm2(const Container& x) { +inline auto norm2(Container&& x) { return apply_vector_unary>::reduce( - to_ref(x), [&](const auto& v) { + to_ref(std::forward(x)), [&](const auto& v) { using T_fvar_inner = typename value_type_t::Scalar; T_fvar_inner res = norm2(v.val()); return fvar(res, diff --git a/stan/math/fwd/fun/pow.hpp b/stan/math/fwd/fun/pow.hpp index 1a23514727a..21a0bf36380 100644 --- a/stan/math/fwd/fun/pow.hpp +++ b/stan/math/fwd/fun/pow.hpp @@ -73,9 +73,13 @@ inline auto pow(const T1& x1, const T2& x2) { template * = nullptr, require_all_not_matrix_st* = nullptr, require_any_fvar_t, base_type_t>* = nullptr> -inline auto pow(const T1& a, const T2& b) { +inline auto pow(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return stan::math::pow(c, d); }, a, b); + [](auto&& c, auto&& d) { + return stan::math::pow(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/fwd/functor/apply_scalar_unary.hpp b/stan/math/fwd/functor/apply_scalar_unary.hpp index 8f37e8f8a65..425eb2af15e 100644 --- a/stan/math/fwd/functor/apply_scalar_unary.hpp +++ b/stan/math/fwd/functor/apply_scalar_unary.hpp @@ -18,12 +18,12 @@ namespace math { * autodiff variable. */ template -struct apply_scalar_unary > { +struct apply_scalar_unary> { /** * Function return type, which is same as the argument type for * the function, fvar<T>. */ - using return_t = fvar; + using return_t = std::decay_t; /** * Apply the function specified by F to the specified argument. @@ -31,7 +31,10 @@ struct apply_scalar_unary > { * @param x Argument variable. * @return Function applied to the variable. */ - static inline return_t apply(const fvar& x) { return F::fun(x); } + template + static inline auto apply(T2&& x) { + return F::fun(std::forward(x)); + } }; } // namespace math diff --git a/stan/math/opencl/prim/dirichlet_lpdf.hpp b/stan/math/opencl/prim/dirichlet_lpdf.hpp index 659071debd3..9887a07ca8e 100644 --- a/stan/math/opencl/prim/dirichlet_lpdf.hpp +++ b/stan/math/opencl/prim/dirichlet_lpdf.hpp @@ -2,6 +2,7 @@ #define STAN_MATH_OPENCL_PRIM_DIRICHLET_LPDF_HPP #ifdef STAN_OPENCL +#include #include #include #include diff --git a/stan/math/prim/constraint/cholesky_corr_constrain.hpp b/stan/math/prim/constraint/cholesky_corr_constrain.hpp index 3a55e04b3f2..5cf2c116e6a 100644 --- a/stan/math/prim/constraint/cholesky_corr_constrain.hpp +++ b/stan/math/prim/constraint/cholesky_corr_constrain.hpp @@ -87,9 +87,10 @@ cholesky_corr_constrain(const EigVec& y, int K, Lp& lp) { * @param K The size of the matrix to return */ template * = nullptr> -inline auto cholesky_corr_constrain(const T& y, int K) { - return apply_vector_unary::apply( - y, [K](auto&& v) { return cholesky_corr_constrain(v, K); }); +inline auto cholesky_corr_constrain(T&& y, int K) { + return apply_vector_unary::apply(std::forward(y), [K](auto&& v) { + return cholesky_corr_constrain(std::forward(v), K); + }); } /** @@ -107,9 +108,10 @@ inline auto cholesky_corr_constrain(const T& y, int K) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto cholesky_corr_constrain(const T& y, int K, Lp& lp) { - return apply_vector_unary::apply( - y, [&lp, K](auto&& v) { return cholesky_corr_constrain(v, K, lp); }); +inline auto cholesky_corr_constrain(T&& y, int K, Lp& lp) { + return apply_vector_unary::apply(std::forward(y), [&lp, K](auto&& v) { + return cholesky_corr_constrain(std::forward(v), K, lp); + }); } /** @@ -132,11 +134,11 @@ inline auto cholesky_corr_constrain(const T& y, int K, Lp& lp) { */ template , Lp>* = nullptr> -inline auto cholesky_corr_constrain(const T& y, int K, Lp& lp) { +inline auto cholesky_corr_constrain(T&& y, int K, Lp& lp) { if constexpr (Jacobian) { - return cholesky_corr_constrain(y, K, lp); + return cholesky_corr_constrain(std::forward(y), K, lp); } else { - return cholesky_corr_constrain(y, K); + return cholesky_corr_constrain(std::forward(y), K); } } diff --git a/stan/math/prim/constraint/cholesky_corr_free.hpp b/stan/math/prim/constraint/cholesky_corr_free.hpp index b359f677313..334895546c4 100644 --- a/stan/math/prim/constraint/cholesky_corr_free.hpp +++ b/stan/math/prim/constraint/cholesky_corr_free.hpp @@ -42,9 +42,10 @@ inline auto cholesky_corr_free(const T& x) { * @param x The standard vector to untransform. */ template * = nullptr> -inline auto cholesky_corr_free(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return cholesky_corr_free(v); }); +inline auto cholesky_corr_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return cholesky_corr_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/cholesky_factor_constrain.hpp b/stan/math/prim/constraint/cholesky_factor_constrain.hpp index 61356d2a897..8b47d199d53 100644 --- a/stan/math/prim/constraint/cholesky_factor_constrain.hpp +++ b/stan/math/prim/constraint/cholesky_factor_constrain.hpp @@ -101,9 +101,10 @@ cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) { * @return Cholesky factor */ template * = nullptr> -inline auto cholesky_factor_constrain(const T& x, int M, int N) { - return apply_vector_unary::apply( - x, [M, N](auto&& v) { return cholesky_factor_constrain(v, M, N); }); +inline auto cholesky_factor_constrain(T&& x, int M, int N) { + return apply_vector_unary::apply(std::forward(x), [M, N](auto&& v) { + return cholesky_factor_constrain(std::forward(v), M, N); + }); } /** @@ -125,9 +126,10 @@ inline auto cholesky_factor_constrain(const T& x, int M, int N) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) { - return apply_vector_unary::apply(x, [&lp, M, N](auto&& v) { - return cholesky_factor_constrain(v, M, N, lp); +inline auto cholesky_factor_constrain(T&& x, int M, int N, Lp& lp) { + return apply_vector_unary::apply(std::forward(x), [&lp, M, + N](auto&& v) { + return cholesky_factor_constrain(std::forward(v), M, N, lp); }); } @@ -155,11 +157,11 @@ inline auto cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) { */ template , Lp>* = nullptr> -inline auto cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) { +inline auto cholesky_factor_constrain(T&& x, int M, int N, Lp& lp) { if constexpr (Jacobian) { - return cholesky_factor_constrain(x, M, N, lp); + return cholesky_factor_constrain(std::forward(x), M, N, lp); } else { - return cholesky_factor_constrain(x, M, N); + return cholesky_factor_constrain(std::forward(x), M, N); } } diff --git a/stan/math/prim/constraint/cholesky_factor_free.hpp b/stan/math/prim/constraint/cholesky_factor_free.hpp index e3be04e2589..7bd879033f6 100644 --- a/stan/math/prim/constraint/cholesky_factor_free.hpp +++ b/stan/math/prim/constraint/cholesky_factor_free.hpp @@ -56,9 +56,10 @@ Eigen::Matrix, Eigen::Dynamic, 1> cholesky_factor_free( * @param x The standard vector to untransform. */ template * = nullptr> -inline auto cholesky_factor_free(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return cholesky_factor_free(v); }); +inline auto cholesky_factor_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return cholesky_factor_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/corr_constrain.hpp b/stan/math/prim/constraint/corr_constrain.hpp index 8366132f9f9..c5cd1862139 100644 --- a/stan/math/prim/constraint/corr_constrain.hpp +++ b/stan/math/prim/constraint/corr_constrain.hpp @@ -24,8 +24,8 @@ namespace math { * @return tanh transform */ template -inline plain_type_t corr_constrain(const T& x) { - return tanh(x); +inline plain_type_t corr_constrain(T&& x) { + return tanh(std::forward(x)); } /** @@ -43,8 +43,8 @@ inline plain_type_t corr_constrain(const T& x) { * @param[in,out] lp log density accumulator */ template -inline auto corr_constrain(const T_x& x, T_lp& lp) { - plain_type_t tanh_x = tanh(x); +inline auto corr_constrain(T_x&& x, T_lp& lp) { + plain_type_t tanh_x = tanh(std::forward(x)); lp += sum(log1m(square(tanh_x))); return tanh_x; } @@ -65,11 +65,11 @@ inline auto corr_constrain(const T_x& x, T_lp& lp) { * @param[in,out] lp log density accumulator */ template -inline auto corr_constrain(const T_x& x, T_lp& lp) { +inline auto corr_constrain(T_x&& x, T_lp& lp) { if constexpr (Jacobian) { - return corr_constrain(x, lp); + return corr_constrain(std::forward(x), lp); } else { - return corr_constrain(x); + return corr_constrain(std::forward(x)); } } diff --git a/stan/math/prim/constraint/corr_free.hpp b/stan/math/prim/constraint/corr_free.hpp index 3714b26f4f1..e094808a0c0 100644 --- a/stan/math/prim/constraint/corr_free.hpp +++ b/stan/math/prim/constraint/corr_free.hpp @@ -25,9 +25,10 @@ namespace math { * @return free scalar that transforms to the specified input */ template -inline plain_type_t corr_free(const T& y) { - check_bounded("lub_free", "Correlation variable", y, -1.0, 1.0); - return atanh(y); +inline plain_type_t corr_free(T&& y) { + auto&& y_ref = to_ref(std::forward(y)); + check_bounded("lub_free", "Correlation variable", y_ref, -1.0, 1.0); + return atanh(std::forward(y_ref)); } } // namespace math diff --git a/stan/math/prim/constraint/corr_matrix_constrain.hpp b/stan/math/prim/constraint/corr_matrix_constrain.hpp index 060b1d5f6a3..f108563c5b7 100644 --- a/stan/math/prim/constraint/corr_matrix_constrain.hpp +++ b/stan/math/prim/constraint/corr_matrix_constrain.hpp @@ -38,11 +38,11 @@ namespace math { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -corr_matrix_constrain(const T& x, Eigen::Index k) { +corr_matrix_constrain(T&& x, Eigen::Index k) { Eigen::Index k_choose_2 = (k * (k - 1)) / 2; check_size_match("cov_matrix_constrain", "x.size()", x.size(), "k_choose_2", k_choose_2); - return read_corr_matrix(corr_constrain(x), k); + return read_corr_matrix(corr_constrain(std::forward(x)), k); } /** @@ -70,11 +70,11 @@ corr_matrix_constrain(const T& x, Eigen::Index k) { template * = nullptr, require_convertible_t, Lp>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -corr_matrix_constrain(const T& x, Eigen::Index k, Lp& lp) { +corr_matrix_constrain(T&& x, Eigen::Index k, Lp& lp) { Eigen::Index k_choose_2 = (k * (k - 1)) / 2; check_size_match("cov_matrix_constrain", "x.size()", x.size(), "k_choose_2", k_choose_2); - return read_corr_matrix(corr_constrain(x, lp), k, lp); + return read_corr_matrix(corr_constrain(std::forward(x), lp), k, lp); } /** @@ -91,9 +91,10 @@ corr_matrix_constrain(const T& x, Eigen::Index k, Lp& lp) { * @param K Dimensionality of returned correlation matrix */ template * = nullptr> -inline auto corr_matrix_constrain(const T& y, int K) { - return apply_vector_unary::apply( - y, [K](auto&& v) { return corr_matrix_constrain(v, K); }); +inline auto corr_matrix_constrain(T&& y, int K) { + return apply_vector_unary::apply(std::forward(y), [K](auto&& v) { + return corr_matrix_constrain(std::forward(v), K); + }); } /** @@ -114,9 +115,10 @@ inline auto corr_matrix_constrain(const T& y, int K) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto corr_matrix_constrain(const T& y, int K, Lp& lp) { - return apply_vector_unary::apply( - y, [&lp, K](auto&& v) { return corr_matrix_constrain(v, K, lp); }); +inline auto corr_matrix_constrain(T&& y, int K, Lp& lp) { + return apply_vector_unary::apply(std::forward(y), [&lp, K](auto&& v) { + return corr_matrix_constrain(std::forward(v), K, lp); + }); } /** @@ -142,11 +144,11 @@ inline auto corr_matrix_constrain(const T& y, int K, Lp& lp) { */ template , Lp>* = nullptr> -inline auto corr_matrix_constrain(const T& x, Eigen::Index k, Lp& lp) { +inline auto corr_matrix_constrain(T&& x, Eigen::Index k, Lp& lp) { if constexpr (Jacobian) { - return corr_matrix_constrain(x, k, lp); + return corr_matrix_constrain(std::forward(x), k, lp); } else { - return corr_matrix_constrain(x, k); + return corr_matrix_constrain(std::forward(x), k); } } diff --git a/stan/math/prim/constraint/corr_matrix_free.hpp b/stan/math/prim/constraint/corr_matrix_free.hpp index 7ddb1230e62..87479eb9e34 100644 --- a/stan/math/prim/constraint/corr_matrix_free.hpp +++ b/stan/math/prim/constraint/corr_matrix_free.hpp @@ -60,9 +60,10 @@ Eigen::Matrix, Eigen::Dynamic, 1> corr_matrix_free(const T& y) { * @param x The standard vector to untransform. */ template * = nullptr> -inline auto corr_matrix_free(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return corr_matrix_free(v); }); +inline auto corr_matrix_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return corr_matrix_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/cov_matrix_constrain.hpp b/stan/math/prim/constraint/cov_matrix_constrain.hpp index 3f2c67b3741..9069a6b0191 100644 --- a/stan/math/prim/constraint/cov_matrix_constrain.hpp +++ b/stan/math/prim/constraint/cov_matrix_constrain.hpp @@ -102,9 +102,10 @@ cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) { * @throws std::domain_error if (x.size() != K + (K choose 2)). */ template * = nullptr> -inline auto cov_matrix_constrain(const T& x, Eigen::Index K) { - return apply_vector_unary::apply( - x, [K](auto&& v) { return cov_matrix_constrain(v, K); }); +inline auto cov_matrix_constrain(T&& x, Eigen::Index K) { + return apply_vector_unary::apply(std::forward(x), [K](auto&& v) { + return cov_matrix_constrain(std::forward(v), K); + }); } /** @@ -124,9 +125,10 @@ inline auto cov_matrix_constrain(const T& x, Eigen::Index K) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) { - return apply_vector_unary::apply( - x, [&lp, K](auto&& v) { return cov_matrix_constrain(v, K, lp); }); +inline auto cov_matrix_constrain(T&& x, Eigen::Index K, Lp& lp) { + return apply_vector_unary::apply(std::forward(x), [&lp, K](auto&& v) { + return cov_matrix_constrain(std::forward(v), K, lp); + }); } /** @@ -151,11 +153,11 @@ inline auto cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) { */ template , Lp>* = nullptr> -inline auto cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) { +inline auto cov_matrix_constrain(T&& x, Eigen::Index K, Lp& lp) { if constexpr (Jacobian) { - return cov_matrix_constrain(x, K, lp); + return cov_matrix_constrain(std::forward(x), K, lp); } else { - return cov_matrix_constrain(x, K); + return cov_matrix_constrain(std::forward(x), K); } } diff --git a/stan/math/prim/constraint/cov_matrix_constrain_lkj.hpp b/stan/math/prim/constraint/cov_matrix_constrain_lkj.hpp index 7f30b7c11c0..798b930247f 100644 --- a/stan/math/prim/constraint/cov_matrix_constrain_lkj.hpp +++ b/stan/math/prim/constraint/cov_matrix_constrain_lkj.hpp @@ -32,9 +32,9 @@ namespace math { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cov_matrix_constrain_lkj(const T& x, size_t k) { +cov_matrix_constrain_lkj(T&& x, size_t k) { size_t k_choose_2 = (k * (k - 1)) / 2; - const auto& x_ref = to_ref(x); + auto&& x_ref = to_ref(std::forward(x)); return read_cov_matrix(corr_constrain(x_ref.head(k_choose_2)), positive_constrain(x_ref.tail(k))); } @@ -56,9 +56,9 @@ cov_matrix_constrain_lkj(const T& x, size_t k) { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cov_matrix_constrain_lkj(const T& x, size_t k, return_type_t& lp) { +cov_matrix_constrain_lkj(T&& x, size_t k, return_type_t& lp) { size_t k_choose_2 = (k * (k - 1)) / 2; - const auto& x_ref = x; + auto&& x_ref = to_ref(std::forward(x)); return read_cov_matrix(corr_constrain(x_ref.head(k_choose_2)), positive_constrain(x_ref.tail(k)), lp); } @@ -84,12 +84,11 @@ cov_matrix_constrain_lkj(const T& x, size_t k, return_type_t& lp) { * correlations and deviations. */ template * = nullptr> -inline auto cov_matrix_constrain_lkj(const T& x, size_t k, - return_type_t& lp) { +inline auto cov_matrix_constrain_lkj(T&& x, size_t k, return_type_t& lp) { if constexpr (Jacobian) { - return cov_matrix_constrain_lkj(x, k, lp); + return cov_matrix_constrain_lkj(std::forward(x), k, lp); } else { - return cov_matrix_constrain_lkj(x, k); + return cov_matrix_constrain_lkj(std::forward(x), k); } } @@ -114,10 +113,10 @@ inline auto cov_matrix_constrain_lkj(const T& x, size_t k, * correlations and deviations. */ template * = nullptr> -inline auto cov_matrix_constrain_lkj(const T& x, size_t k, - return_type_t& lp) { - return apply_vector_unary::apply(x, [&lp, k](auto&& v) { - return cov_matrix_constrain_lkj(v, k, lp); +inline auto cov_matrix_constrain_lkj(T&& x, size_t k, return_type_t& lp) { + return apply_vector_unary::apply(std::forward(x), [&lp, k](auto&& v) { + return cov_matrix_constrain_lkj(std::forward(v), k, + lp); }); } diff --git a/stan/math/prim/constraint/cov_matrix_free.hpp b/stan/math/prim/constraint/cov_matrix_free.hpp index 4fcff40b647..6324d2c61e9 100644 --- a/stan/math/prim/constraint/cov_matrix_free.hpp +++ b/stan/math/prim/constraint/cov_matrix_free.hpp @@ -66,9 +66,10 @@ Eigen::Matrix, Eigen::Dynamic, 1> cov_matrix_free(const T& y) { * @param x The standard vector to untransform. */ template * = nullptr> -inline auto cov_matrix_free(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return cov_matrix_free(v); }); +inline auto cov_matrix_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return cov_matrix_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/cov_matrix_free_lkj.hpp b/stan/math/prim/constraint/cov_matrix_free_lkj.hpp index b0d6c94f7a8..a2fa9764a19 100644 --- a/stan/math/prim/constraint/cov_matrix_free_lkj.hpp +++ b/stan/math/prim/constraint/cov_matrix_free_lkj.hpp @@ -57,9 +57,10 @@ Eigen::Matrix, Eigen::Dynamic, 1> cov_matrix_free_lkj( * @param x The standard vector to untransform. */ template * = nullptr> -auto cov_matrix_free_lkj(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return cov_matrix_free_lkj(v); }); +auto cov_matrix_free_lkj(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return cov_matrix_free_lkj(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/identity_constrain.hpp b/stan/math/prim/constraint/identity_constrain.hpp index 00590438700..4d5ae105b4d 100644 --- a/stan/math/prim/constraint/identity_constrain.hpp +++ b/stan/math/prim/constraint/identity_constrain.hpp @@ -21,7 +21,7 @@ namespace math { template * = nullptr> inline auto identity_constrain(T&& x, Types&&... /* args */) { - return promote_scalar_t, T>(x); + return promote_scalar_t, T>(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/constraint/identity_free.hpp b/stan/math/prim/constraint/identity_free.hpp index ef5925c2355..2686d8fae5c 100644 --- a/stan/math/prim/constraint/identity_free.hpp +++ b/stan/math/prim/constraint/identity_free.hpp @@ -20,7 +20,7 @@ namespace math { template * = nullptr> inline auto identity_free(T&& x, Types&&... /* args */) { - return promote_scalar_t, T>(x); + return promote_scalar_t, T>(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/constraint/lb_constrain.hpp b/stan/math/prim/constraint/lb_constrain.hpp index 8f09c7733aa..3a59059873c 100644 --- a/stan/math/prim/constraint/lb_constrain.hpp +++ b/stan/math/prim/constraint/lb_constrain.hpp @@ -255,11 +255,11 @@ inline auto lb_constrain(const std::vector& x, const std::vector& lb, */ template , Lp>* = nullptr> -inline auto lb_constrain(const T& x, const L& lb, Lp& lp) { +inline auto lb_constrain(T&& x, L&& lb, Lp& lp) { if constexpr (Jacobian) { - return lb_constrain(x, lb, lp); + return lb_constrain(std::forward(x), std::forward(lb), lp); } else { - return lb_constrain(x, lb); + return lb_constrain(std::forward(x), std::forward(lb)); } } diff --git a/stan/math/prim/constraint/lb_free.hpp b/stan/math/prim/constraint/lb_free.hpp index f5e80d700e6..5542be2505c 100644 --- a/stan/math/prim/constraint/lb_free.hpp +++ b/stan/math/prim/constraint/lb_free.hpp @@ -29,7 +29,7 @@ template * = nullptr, require_stan_scalar_t* = nullptr> inline auto lb_free(T&& y, L&& lb) { if (value_of_rec(lb) == NEGATIVE_INFTY) { - return identity_free(y, lb); + return identity_free(std::forward(y), lb); } else { auto&& y_ref = to_ref(std::forward(y)); auto&& lb_ref = to_ref(std::forward(lb)); diff --git a/stan/math/prim/constraint/lub_constrain.hpp b/stan/math/prim/constraint/lub_constrain.hpp index 6b2a9c623ad..4e5326d6828 100644 --- a/stan/math/prim/constraint/lub_constrain.hpp +++ b/stan/math/prim/constraint/lub_constrain.hpp @@ -398,11 +398,13 @@ inline auto lub_constrain(const std::vector& x, const std::vector& lb, */ template , Lp>* = nullptr> -inline auto lub_constrain(const T& x, const L& lb, const U& ub, Lp& lp) { +inline auto lub_constrain(T&& x, L&& lb, U&& ub, Lp& lp) { if constexpr (Jacobian) { - return lub_constrain(x, lb, ub, lp); + return lub_constrain(std::forward(x), std::forward(lb), + std::forward(ub), lp); } else { - return lub_constrain(x, lb, ub); + return lub_constrain(std::forward(x), std::forward(lb), + std::forward(ub)); } } @@ -410,8 +412,9 @@ inline auto lub_constrain(const T& x, const L& lb, const U& ub, Lp& lp) { * Wrapper for tuple of bounds, simply delegates to the appropriate overload */ template -inline auto lub_constrain(const T& x, const std::tuple& bounds) { - return lub_constrain(x, std::get<0>(bounds), std::get<1>(bounds)); +inline auto lub_constrain(T&& x, const std::tuple& bounds) { + return lub_constrain(std::forward(x), std::get<0>(bounds), + std::get<1>(bounds)); } /** @@ -419,8 +422,9 @@ inline auto lub_constrain(const T& x, const std::tuple& bounds) { */ template , Lp>* = nullptr> -inline auto lub_constrain(const T& x, const std::tuple& bounds, Lp& lp) { - return lub_constrain(x, std::get<0>(bounds), std::get<1>(bounds), lp); +inline auto lub_constrain(T&& x, const std::tuple& bounds, Lp& lp) { + return lub_constrain(std::forward(x), std::get<0>(bounds), + std::get<1>(bounds), lp); } /** @@ -428,9 +432,9 @@ inline auto lub_constrain(const T& x, const std::tuple& bounds, Lp& lp) { */ template , Lp>* = nullptr> -inline auto lub_constrain(const T& x, const std::tuple& bounds, Lp& lp) { - return lub_constrain(x, std::get<0>(bounds), std::get<1>(bounds), - lp); +inline auto lub_constrain(T&& x, const std::tuple& bounds, Lp& lp) { + return lub_constrain(std::forward(x), std::get<0>(bounds), + std::get<1>(bounds), lp); } } // namespace math diff --git a/stan/math/prim/constraint/offset_multiplier_constrain.hpp b/stan/math/prim/constraint/offset_multiplier_constrain.hpp index 186c8f38988..640110f56d3 100644 --- a/stan/math/prim/constraint/offset_multiplier_constrain.hpp +++ b/stan/math/prim/constraint/offset_multiplier_constrain.hpp @@ -303,12 +303,13 @@ inline auto offset_multiplier_constrain(const std::vector& x, */ template , Lp>* = nullptr> -inline auto offset_multiplier_constrain(const T& x, const M& mu, const S& sigma, - Lp& lp) { +inline auto offset_multiplier_constrain(T&& x, M&& mu, S&& sigma, Lp& lp) { if constexpr (Jacobian) { - return offset_multiplier_constrain(x, mu, sigma, lp); + return offset_multiplier_constrain(std::forward(x), std::forward(mu), + std::forward(sigma), lp); } else { - return offset_multiplier_constrain(x, mu, sigma); + return offset_multiplier_constrain(std::forward(x), std::forward(mu), + std::forward(sigma)); } } diff --git a/stan/math/prim/constraint/ordered_constrain.hpp b/stan/math/prim/constraint/ordered_constrain.hpp index 9fab8f2225d..8cbc3dfbf91 100644 --- a/stan/math/prim/constraint/ordered_constrain.hpp +++ b/stan/math/prim/constraint/ordered_constrain.hpp @@ -23,11 +23,11 @@ namespace math { */ template * = nullptr, require_not_st_var* = nullptr> -inline plain_type_t ordered_constrain(const EigVec& x) { +inline plain_type_t ordered_constrain(EigVec&& x) { using std::exp; - Eigen::Index k = x.size(); + auto&& x_ref = to_ref(std::forward(x)); + Eigen::Index k = x_ref.size(); plain_type_t y(k); - const auto& x_ref = to_ref(x); if (unlikely(k == 0)) { return y; } @@ -55,12 +55,12 @@ inline plain_type_t ordered_constrain(const EigVec& x) { template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto ordered_constrain(const EigVec& x, Lp& lp) { - const auto& x_ref = to_ref(x); - if (likely(x.size() > 1)) { +inline auto ordered_constrain(EigVec&& x, Lp& lp) { + auto&& x_ref = to_ref(std::forward(x)); + if (likely(x_ref.size() > 1)) { lp += sum(x_ref.tail(x.size() - 1)); } - return ordered_constrain(x_ref); + return ordered_constrain(std::forward(x_ref)); } /** @@ -76,9 +76,10 @@ inline auto ordered_constrain(const EigVec& x, Lp& lp) { * @return Positive, increasing ordered vector. */ template * = nullptr> -inline auto ordered_constrain(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return ordered_constrain(v); }); +inline auto ordered_constrain(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return ordered_constrain(std::forward(v)); + }); } /** @@ -98,9 +99,10 @@ inline auto ordered_constrain(const T& x) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto ordered_constrain(const T& x, Lp& lp) { - return apply_vector_unary::apply( - x, [&lp](auto&& v) { return ordered_constrain(v, lp); }); +inline auto ordered_constrain(T&& x, Lp& lp) { + return apply_vector_unary::apply(std::forward(x), [&lp](auto&& v) { + return ordered_constrain(std::forward(v), lp); + }); } /** @@ -125,11 +127,11 @@ inline auto ordered_constrain(const T& x, Lp& lp) { */ template , Lp>* = nullptr> -inline auto ordered_constrain(const T& x, Lp& lp) { +inline auto ordered_constrain(T&& x, Lp& lp) { if constexpr (Jacobian) { - return ordered_constrain(x, lp); + return ordered_constrain(std::forward(x), lp); } else { - return ordered_constrain(x); + return ordered_constrain(std::forward(x)); } } diff --git a/stan/math/prim/constraint/ordered_free.hpp b/stan/math/prim/constraint/ordered_free.hpp index 297bae0b062..03058fb57cf 100644 --- a/stan/math/prim/constraint/ordered_free.hpp +++ b/stan/math/prim/constraint/ordered_free.hpp @@ -49,9 +49,10 @@ plain_type_t ordered_free(const EigVec& y) { * @param x The standard vector to untransform. */ template * = nullptr> -inline auto ordered_free(const T& x) { - return apply_vector_unary::apply(x, - [](auto&& v) { return ordered_free(v); }); +inline auto ordered_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return ordered_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/positive_constrain.hpp b/stan/math/prim/constraint/positive_constrain.hpp index cd8147ec78f..67ed40eb0c0 100644 --- a/stan/math/prim/constraint/positive_constrain.hpp +++ b/stan/math/prim/constraint/positive_constrain.hpp @@ -20,8 +20,8 @@ namespace math { * @return Input transformed to be positive. */ template -inline auto positive_constrain(const T& x) { - return exp(x); +inline auto positive_constrain(T&& x) { + return exp(std::forward(x)); } /** @@ -41,9 +41,10 @@ inline auto positive_constrain(const T& x) { * @return positive constrained version of unconstrained value(s) */ template -inline auto positive_constrain(const T& x, S& lp) { - lp += sum(x); - return exp(x); +inline auto positive_constrain(T&& x, S& lp) { + auto&& x_ref = to_ref(std::forward(x)); + lp += sum(x_ref); + return exp(std::forward(x)); } /** @@ -66,11 +67,11 @@ inline auto positive_constrain(const T& x, S& lp) { template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto positive_constrain(const T& x, Lp& lp) { +inline auto positive_constrain(T&& x, Lp& lp) { if constexpr (Jacobian) { - return positive_constrain(x, lp); + return positive_constrain(std::forward(x), lp); } else { - return positive_constrain(x); + return positive_constrain(std::forward(x)); } } @@ -95,9 +96,10 @@ inline auto positive_constrain(const T& x, Lp& lp) { template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto positive_constrain(const T& x, Lp& lp) { - return apply_vector_unary::apply( - x, [&lp](auto&& v) { return positive_constrain(v, lp); }); +inline auto positive_constrain(T&& x, Lp& lp) { + return apply_vector_unary::apply(std::forward(x), [&lp](auto&& v) { + return positive_constrain(std::forward(v), lp); + }); } } // namespace math diff --git a/stan/math/prim/constraint/positive_free.hpp b/stan/math/prim/constraint/positive_free.hpp index ba76d16123f..2e3637e2b94 100644 --- a/stan/math/prim/constraint/positive_free.hpp +++ b/stan/math/prim/constraint/positive_free.hpp @@ -26,9 +26,10 @@ namespace math { * @throw std::domain_error if the variable is negative */ template -inline plain_type_t positive_free(const T& y) { - check_positive("positive_free", "Positive variable", y); - return log(y); +inline auto positive_free(T&& y) { + auto&& y_ref = to_ref(std::forward(y)); + check_positive("positive_free", "Positive variable", y_ref); + return log(std::forward(y_ref)); } } // namespace math diff --git a/stan/math/prim/constraint/positive_ordered_constrain.hpp b/stan/math/prim/constraint/positive_ordered_constrain.hpp index 4d1f228814f..4428151e9ec 100644 --- a/stan/math/prim/constraint/positive_ordered_constrain.hpp +++ b/stan/math/prim/constraint/positive_ordered_constrain.hpp @@ -53,10 +53,10 @@ inline auto positive_ordered_constrain(const EigVec& x) { template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto positive_ordered_constrain(const Vec& x, Lp& lp) { - const auto& x_ref = to_ref(x); +inline auto positive_ordered_constrain(Vec&& x, Lp& lp) { + auto&& x_ref = to_ref(std::forward(x)); lp += sum(x_ref); - return positive_ordered_constrain(x_ref); + return positive_ordered_constrain(std::forward(x_ref)); } /** @@ -71,9 +71,10 @@ inline auto positive_ordered_constrain(const Vec& x, Lp& lp) { * @return Positive, increasing ordered vector */ template * = nullptr> -inline auto positive_ordered_constrain(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return positive_ordered_constrain(v); }); +inline auto positive_ordered_constrain(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return positive_ordered_constrain(std::forward(v)); + }); } /** @@ -92,9 +93,10 @@ inline auto positive_ordered_constrain(const T& x) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto positive_ordered_constrain(const T& x, Lp& lp) { - return apply_vector_unary::apply( - x, [&lp](auto&& v) { return positive_ordered_constrain(v, lp); }); +inline auto positive_ordered_constrain(T&& x, Lp& lp) { + return apply_vector_unary::apply(std::forward(x), [&lp](auto&& v) { + return positive_ordered_constrain(std::forward(v), lp); + }); } /** @@ -118,11 +120,11 @@ inline auto positive_ordered_constrain(const T& x, Lp& lp) { */ template , Lp>* = nullptr> -inline auto positive_ordered_constrain(const Vec& x, Lp& lp) { +inline auto positive_ordered_constrain(Vec&& x, Lp& lp) { if constexpr (Jacobian) { - return positive_ordered_constrain(x, lp); + return positive_ordered_constrain(std::forward(x), lp); } else { - return positive_ordered_constrain(x); + return positive_ordered_constrain(std::forward(x)); } } diff --git a/stan/math/prim/constraint/positive_ordered_free.hpp b/stan/math/prim/constraint/positive_ordered_free.hpp index a28052ec89e..face9f638e4 100644 --- a/stan/math/prim/constraint/positive_ordered_free.hpp +++ b/stan/math/prim/constraint/positive_ordered_free.hpp @@ -49,9 +49,10 @@ inline auto positive_ordered_free(const EigVec& y) { * @param x The standard vector to untransform. */ template * = nullptr> -inline auto positive_ordered_free(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return positive_ordered_free(v); }); +inline auto positive_ordered_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return positive_ordered_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/prob_constrain.hpp b/stan/math/prim/constraint/prob_constrain.hpp index d05193c8648..70bfea6203e 100644 --- a/stan/math/prim/constraint/prob_constrain.hpp +++ b/stan/math/prim/constraint/prob_constrain.hpp @@ -23,8 +23,8 @@ namespace math { * @return result constrained to fall in (0, 1) */ template -inline T prob_constrain(const T& x) { - return inv_logit(x); +inline auto prob_constrain(T&& x) { + return inv_logit(std::forward(x)); } /** @@ -47,11 +47,11 @@ inline T prob_constrain(const T& x) { * @param[in, out] lp log density * @return result constrained to fall in (0, 1) */ -template -inline T prob_constrain(const T& x, T& lp) { - T log_inv_logit_x = log_inv_logit(x); - lp += log_inv_logit_x + log1m_inv_logit(x); - return exp(log_inv_logit_x); +template +inline auto prob_constrain(T&& x, Lp& lp) { + std::decay_t log_inv_logit_x = log_inv_logit(x); + lp += log_inv_logit_x + log1m_inv_logit(std::forward(x)); + return exp(std::move(log_inv_logit_x)); } /** @@ -68,12 +68,12 @@ inline T prob_constrain(const T& x, T& lp) { * @param[in, out] lp log density accumulator * @return result constrained to fall in (0, 1) */ -template -inline auto prob_constrain(const T& x, T& lp) { +template +inline auto prob_constrain(T&& x, Lp& lp) { if (Jacobian) { - return prob_constrain(x, lp); + return prob_constrain(std::forward(x), lp); } else { - return prob_constrain(x); + return prob_constrain(std::forward(x)); } } } // namespace math diff --git a/stan/math/prim/constraint/prob_free.hpp b/stan/math/prim/constraint/prob_free.hpp index 0f980ab87cd..1706ae2f79f 100644 --- a/stan/math/prim/constraint/prob_free.hpp +++ b/stan/math/prim/constraint/prob_free.hpp @@ -24,10 +24,11 @@ namespace math { * @throw std::domain_error if y is not in (0, 1) */ template -inline T prob_free(const T& y) { - check_bounded("prob_free", "Probability variable", y, 0, - 1); - return logit(y); +inline auto prob_free(T&& y) { + auto&& y_ref = to_ref(std::forward(y)); + check_bounded, double, double>( + "prob_free", "Probability variable", y_ref, 0, 1); + return logit(std::forward(y_ref)); } } // namespace math diff --git a/stan/math/prim/constraint/simplex_constrain.hpp b/stan/math/prim/constraint/simplex_constrain.hpp index cdae665c1e8..d3a9c49834e 100644 --- a/stan/math/prim/constraint/simplex_constrain.hpp +++ b/stan/math/prim/constraint/simplex_constrain.hpp @@ -145,9 +145,10 @@ inline plain_type_t simplex_constrain(const Vec& y, Lp& lp) { * @return simplex of dimensionality one greater than `y` */ template * = nullptr> -inline auto simplex_constrain(const T& y) { - return apply_vector_unary::apply( - y, [](auto&& v) { return simplex_constrain(v); }); +inline auto simplex_constrain(T&& y) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return simplex_constrain(std::forward(v)); + }); } /** @@ -165,9 +166,10 @@ inline auto simplex_constrain(const T& y) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto simplex_constrain(const T& y, Lp& lp) { - return apply_vector_unary::apply( - y, [&lp](auto&& v) { return simplex_constrain(v, lp); }); +inline auto simplex_constrain(T&& y, Lp& lp) { + return apply_vector_unary::apply(std::forward(y), [&lp](auto&& v) { + return simplex_constrain(std::forward(v), lp); + }); } /** @@ -190,11 +192,11 @@ inline auto simplex_constrain(const T& y, Lp& lp) { */ template , Lp>* = nullptr> -inline plain_type_t simplex_constrain(const Vec& y, Lp& lp) { +inline plain_type_t simplex_constrain(Vec&& y, Lp& lp) { if constexpr (Jacobian) { - return simplex_constrain(y, lp); + return simplex_constrain(std::forward(y), lp); } else { - return simplex_constrain(y); + return simplex_constrain(std::forward(y)); } } diff --git a/stan/math/prim/constraint/simplex_free.hpp b/stan/math/prim/constraint/simplex_free.hpp index 4c4a27c33bd..8a6340a0431 100644 --- a/stan/math/prim/constraint/simplex_free.hpp +++ b/stan/math/prim/constraint/simplex_free.hpp @@ -53,9 +53,10 @@ inline plain_type_t simplex_free(const Vec& x) { * @param x The standard vector to untransform. */ template * = nullptr> -inline auto simplex_free(const T& x) { - return apply_vector_unary::apply(x, - [](auto&& v) { return simplex_free(v); }); +inline auto simplex_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return simplex_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/stochastic_column_constrain.hpp b/stan/math/prim/constraint/stochastic_column_constrain.hpp index 58ef35ea0f6..4de8441fce8 100644 --- a/stan/math/prim/constraint/stochastic_column_constrain.hpp +++ b/stan/math/prim/constraint/stochastic_column_constrain.hpp @@ -71,9 +71,10 @@ inline plain_type_t stochastic_column_constrain(const Mat& y, Lp& lp) { * dimensionality (K, M). */ template * = nullptr> -inline auto stochastic_column_constrain(const T& y) { - return apply_vector_unary::apply( - y, [](auto&& v) { return stochastic_column_constrain(v); }); +inline auto stochastic_column_constrain(T&& y) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return stochastic_column_constrain(std::forward(v)); + }); } /** @@ -92,9 +93,10 @@ inline auto stochastic_column_constrain(const T& y) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto stochastic_column_constrain(const T& y, Lp& lp) { - return apply_vector_unary::apply( - y, [&lp](auto&& v) { return stochastic_column_constrain(v, lp); }); +inline auto stochastic_column_constrain(T&& y, Lp& lp) { + return apply_vector_unary::apply(std::forward(y), [&lp](auto&& v) { + return stochastic_column_constrain(std::forward(v), lp); + }); } /** @@ -117,11 +119,11 @@ inline auto stochastic_column_constrain(const T& y, Lp& lp) { */ template , Lp>* = nullptr> -inline plain_type_t stochastic_column_constrain(const Mat& y, Lp& lp) { +inline plain_type_t stochastic_column_constrain(Mat&& y, Lp& lp) { if constexpr (Jacobian) { - return stochastic_column_constrain(y, lp); + return stochastic_column_constrain(std::forward(y), lp); } else { - return stochastic_column_constrain(y); + return stochastic_column_constrain(std::forward(y)); } } diff --git a/stan/math/prim/constraint/stochastic_column_free.hpp b/stan/math/prim/constraint/stochastic_column_free.hpp index 988a579d2d3..1e121a59855 100644 --- a/stan/math/prim/constraint/stochastic_column_free.hpp +++ b/stan/math/prim/constraint/stochastic_column_free.hpp @@ -36,9 +36,10 @@ inline plain_type_t stochastic_column_free(const Mat& y) { * @param[in] y vector of columnwise stochastic matrix of size (N, K) */ template * = nullptr> -inline auto stochastic_column_free(const T& y) { - return apply_vector_unary::apply( - y, [](auto&& v) { return stochastic_column_free(v); }); +inline auto stochastic_column_free(T&& y) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return stochastic_column_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/stochastic_row_constrain.hpp b/stan/math/prim/constraint/stochastic_row_constrain.hpp index 290f3d3b72f..7c227ee4eb4 100644 --- a/stan/math/prim/constraint/stochastic_row_constrain.hpp +++ b/stan/math/prim/constraint/stochastic_row_constrain.hpp @@ -68,9 +68,10 @@ inline plain_type_t stochastic_row_constrain(const Mat& y, Lp& lp) { * @return vector of matrices with simplex rows of dimensionality (N, K) */ template * = nullptr> -inline auto stochastic_row_constrain(const T& y) { - return apply_vector_unary::apply( - y, [](auto&& v) { return stochastic_row_constrain(v); }); +inline auto stochastic_row_constrain(T&& y) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return stochastic_row_constrain(std::forward(v)); + }); } /** @@ -88,9 +89,10 @@ inline auto stochastic_row_constrain(const T& y) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto stochastic_row_constrain(const T& y, Lp& lp) { - return apply_vector_unary::apply( - y, [&lp](auto&& v) { return stochastic_row_constrain(v, lp); }); +inline auto stochastic_row_constrain(T&& y, Lp& lp) { + return apply_vector_unary::apply(std::forward(y), [&lp](auto&& v) { + return stochastic_row_constrain(std::forward(v), lp); + }); } /** @@ -113,11 +115,11 @@ inline auto stochastic_row_constrain(const T& y, Lp& lp) { */ template , Lp>* = nullptr> -inline plain_type_t stochastic_row_constrain(const Mat& y, Lp& lp) { +inline plain_type_t stochastic_row_constrain(Mat&& y, Lp& lp) { if constexpr (Jacobian) { - return stochastic_row_constrain(y, lp); + return stochastic_row_constrain(std::forward(y), lp); } else { - return stochastic_row_constrain(y); + return stochastic_row_constrain(std::forward(y)); } } diff --git a/stan/math/prim/constraint/stochastic_row_free.hpp b/stan/math/prim/constraint/stochastic_row_free.hpp index 069db772d66..20d7be9fdee 100644 --- a/stan/math/prim/constraint/stochastic_row_free.hpp +++ b/stan/math/prim/constraint/stochastic_row_free.hpp @@ -35,9 +35,10 @@ inline plain_type_t stochastic_row_free(const Mat& y) { * @param[in] y vector of rowwise simplex matrices each of size (N, K) */ template * = nullptr> -inline auto stochastic_row_free(const T& y) { - return apply_vector_unary::apply( - y, [](auto&& v) { return stochastic_row_free(v); }); +inline auto stochastic_row_free(T&& y) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return stochastic_row_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/sum_to_zero_constrain.hpp b/stan/math/prim/constraint/sum_to_zero_constrain.hpp index 19f330c5692..3767fa967a5 100644 --- a/stan/math/prim/constraint/sum_to_zero_constrain.hpp +++ b/stan/math/prim/constraint/sum_to_zero_constrain.hpp @@ -123,8 +123,8 @@ inline plain_type_t sum_to_zero_constrain(const Mat& x) { * @return Zero-sum vector or matrix which is one larger in each dimension */ template * = nullptr> -inline plain_type_t sum_to_zero_constrain(const T& y, Lp& lp) { - return sum_to_zero_constrain(y); +inline plain_type_t sum_to_zero_constrain(T&& y, Lp& lp) { + return sum_to_zero_constrain(std::forward(y)); } /** @@ -138,9 +138,10 @@ inline plain_type_t sum_to_zero_constrain(const T& y, Lp& lp) { * @return Zero-sum vectors or matrices which are one larger in each dimension */ template * = nullptr> -inline auto sum_to_zero_constrain(const T& y) { - return apply_vector_unary::apply( - y, [](auto&& v) { return sum_to_zero_constrain(v); }); +inline auto sum_to_zero_constrain(T&& y) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return sum_to_zero_constrain(std::forward(v)); + }); } /** @@ -157,9 +158,10 @@ inline auto sum_to_zero_constrain(const T& y) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto sum_to_zero_constrain(const T& y, Lp& lp) { - return apply_vector_unary::apply( - y, [](auto&& v) { return sum_to_zero_constrain(v); }); +inline auto sum_to_zero_constrain(T&& y, Lp& lp) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return sum_to_zero_constrain(std::forward(v)); + }); } /** @@ -175,8 +177,8 @@ inline auto sum_to_zero_constrain(const T& y, Lp& lp) { * @return Zero-sum vector or matrix which is one larger in each dimension */ template -inline plain_type_t sum_to_zero_constrain(const T& y, Lp& lp) { - return sum_to_zero_constrain(y); +inline plain_type_t sum_to_zero_constrain(T&& y, Lp& lp) { + return sum_to_zero_constrain(std::forward(y)); } } // namespace math diff --git a/stan/math/prim/constraint/sum_to_zero_free.hpp b/stan/math/prim/constraint/sum_to_zero_free.hpp index 4acbbdfacdd..b7c5e44e004 100644 --- a/stan/math/prim/constraint/sum_to_zero_free.hpp +++ b/stan/math/prim/constraint/sum_to_zero_free.hpp @@ -115,9 +115,10 @@ inline plain_type_t sum_to_zero_free(const Mat& z) { * @param z The standard vector to untransform. */ template * = nullptr> -inline auto sum_to_zero_free(const T& z) { - return apply_vector_unary::apply( - z, [](auto&& v) { return sum_to_zero_free(v); }); +inline auto sum_to_zero_free(T&& z) { + return apply_vector_unary::apply(std::forward(z), [](auto&& v) { + return sum_to_zero_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/constraint/ub_constrain.hpp b/stan/math/prim/constraint/ub_constrain.hpp index fe836471456..f779990b43d 100644 --- a/stan/math/prim/constraint/ub_constrain.hpp +++ b/stan/math/prim/constraint/ub_constrain.hpp @@ -261,11 +261,11 @@ inline auto ub_constrain(const std::vector& x, const std::vector& ub, */ template , Lp>* = nullptr> -inline auto ub_constrain(const T& x, const U& ub, Lp& lp) { +inline auto ub_constrain(T&& x, U&& ub, Lp& lp) { if constexpr (Jacobian) { - return ub_constrain(x, ub, lp); + return ub_constrain(std::forward(x), std::forward(ub), lp); } else { - return ub_constrain(x, ub); + return ub_constrain(std::forward(x), std::forward(ub)); } } diff --git a/stan/math/prim/constraint/unit_vector_constrain.hpp b/stan/math/prim/constraint/unit_vector_constrain.hpp index ae72f6277a1..f1520f79aa1 100644 --- a/stan/math/prim/constraint/unit_vector_constrain.hpp +++ b/stan/math/prim/constraint/unit_vector_constrain.hpp @@ -66,9 +66,10 @@ inline plain_type_t unit_vector_constrain(const T1& y, T2& lp) { * @return Unit length vector of dimension K */ template * = nullptr> -inline auto unit_vector_constrain(const T& y) { - return apply_vector_unary::apply( - y, [](auto&& v) { return unit_vector_constrain(v); }); +inline auto unit_vector_constrain(T&& y) { + return apply_vector_unary::apply(std::forward(y), [](auto&& v) { + return unit_vector_constrain(std::forward(v)); + }); } /** @@ -86,9 +87,10 @@ inline auto unit_vector_constrain(const T& y) { */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto unit_vector_constrain(const T& y, Lp& lp) { - return apply_vector_unary::apply( - y, [&lp](auto&& v) { return unit_vector_constrain(v, lp); }); +inline auto unit_vector_constrain(T&& y, Lp& lp) { + return apply_vector_unary::apply(std::forward(y), [&lp](auto&& v) { + return unit_vector_constrain(std::forward(v), lp); + }); } /** @@ -111,11 +113,11 @@ inline auto unit_vector_constrain(const T& y, Lp& lp) { */ template , Lp>* = nullptr> -inline auto unit_vector_constrain(const T& y, Lp& lp) { +inline auto unit_vector_constrain(T&& y, Lp& lp) { if constexpr (Jacobian) { - return unit_vector_constrain(y, lp); + return unit_vector_constrain(std::forward(y), lp); } else { - return unit_vector_constrain(y); + return unit_vector_constrain(std::forward(y)); } } diff --git a/stan/math/prim/constraint/unit_vector_free.hpp b/stan/math/prim/constraint/unit_vector_free.hpp index c0debd3429e..c69a7ac9421 100644 --- a/stan/math/prim/constraint/unit_vector_free.hpp +++ b/stan/math/prim/constraint/unit_vector_free.hpp @@ -36,9 +36,10 @@ inline auto unit_vector_free(EigVec&& x) { * @param x The standard vector to untransform. */ template * = nullptr> -inline auto unit_vector_free(const T& x) { - return apply_vector_unary::apply( - x, [](auto&& v) { return unit_vector_free(v); }); +inline auto unit_vector_free(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& v) { + return unit_vector_free(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/prim/fun/Phi.hpp b/stan/math/prim/fun/Phi.hpp index 152ab151bcf..0ae82a61755 100644 --- a/stan/math/prim/fun/Phi.hpp +++ b/stan/math/prim/fun/Phi.hpp @@ -51,8 +51,8 @@ inline double Phi(double x) { */ struct Phi_fun { template - static inline auto fun(const T& x) { - return Phi(x); + static inline auto fun(T&& x) { + return Phi(std::forward(x)); } }; @@ -66,9 +66,9 @@ struct Phi_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto Phi(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> +inline auto Phi(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/Phi_approx.hpp b/stan/math/prim/fun/Phi_approx.hpp index 555a06a2c41..8351cb13e49 100644 --- a/stan/math/prim/fun/Phi_approx.hpp +++ b/stan/math/prim/fun/Phi_approx.hpp @@ -47,8 +47,8 @@ struct Phi_approx_fun { * @return approximate value of Phi applied to argument */ template - static inline auto fun(const T& x) { - return Phi_approx(x); + static inline auto fun(T&& x) { + return Phi_approx(std::forward(x)); } }; @@ -65,9 +65,9 @@ struct Phi_approx_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto Phi_approx(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> +inline auto Phi_approx(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/abs.hpp b/stan/math/prim/fun/abs.hpp index fca073133ec..443cc97405e 100644 --- a/stan/math/prim/fun/abs.hpp +++ b/stan/math/prim/fun/abs.hpp @@ -22,7 +22,7 @@ namespace math { * @return absolute value of argument */ template * = nullptr> -inline T abs(T x) { +inline auto abs(T&& x) { return std::abs(x); } @@ -35,7 +35,7 @@ inline T abs(T x) { * @return absolute value of argument (a real number) */ template * = nullptr> -inline auto abs(T x) { +inline auto abs(T&& x) { return std::hypot(x.real(), x.imag()); } @@ -49,8 +49,12 @@ inline auto abs(T x) { */ struct abs_fun { template - static inline auto fun(const T& x) { - return abs(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::abs(x); + } else { + return abs(std::forward(x)); + } } }; @@ -63,8 +67,9 @@ struct abs_fun { * @return Absolute value of each variable in the container. */ template * = nullptr> -inline auto abs(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto abs(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -77,9 +82,10 @@ inline auto abs(const Container& x) { */ template * = nullptr> -inline auto abs(const Container& x) { +inline auto abs(Container&& x) { return apply_vector_unary::apply( - x, [&](const auto& v) { return v.array().abs(); }); + std::forward(x), + [&](const auto& v) { return v.array().abs(); }); } namespace internal { diff --git a/stan/math/prim/fun/acos.hpp b/stan/math/prim/fun/acos.hpp index 1efa76b5174..f1ff88c11b3 100644 --- a/stan/math/prim/fun/acos.hpp +++ b/stan/math/prim/fun/acos.hpp @@ -26,7 +26,7 @@ namespace math { * @return arc cosine of the argument */ template * = nullptr> -inline auto acos(const T x) { +inline auto acos(T&& x) { return std::acos(x); } @@ -38,7 +38,7 @@ inline auto acos(const T x) { * @return arc cosine of the argument */ template * = nullptr> -inline auto acos(const T x) { +inline auto acos(T&& x) { return std::acos(x); } @@ -51,8 +51,12 @@ inline auto acos(const T x) { */ struct acos_fun { template - static inline auto fun(const T& x) { - return acos(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::acos(x); + } else { + return acos(std::forward(x)); + } } }; @@ -65,8 +69,9 @@ struct acos_fun { * @return Arc cosine of each variable in the container, in radians. */ template * = nullptr> -inline auto acos(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto acos(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -79,9 +84,9 @@ inline auto acos(const Container& x) { */ template * = nullptr> -inline auto acos(const Container& x) { +inline auto acos(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().acos(); }); + std::forward(x), [](auto&& v) { return v.array().acos(); }); } namespace internal { diff --git a/stan/math/prim/fun/acosh.hpp b/stan/math/prim/fun/acosh.hpp index 5580e9e1e73..83d8e17da3a 100644 --- a/stan/math/prim/fun/acosh.hpp +++ b/stan/math/prim/fun/acosh.hpp @@ -24,7 +24,7 @@ namespace math { * @throw std::domain_error If argument is less than 1. */ template * = nullptr> -inline double acosh(const T x) { +inline double acosh(T&& x) { if (is_nan(x)) { return x; } else { @@ -46,7 +46,7 @@ inline double acosh(const T x) { * @throw std::domain_error If argument is less than 1. */ template * = nullptr> -inline auto acosh(const T x) { +inline auto acosh(T&& x) { return std::acosh(x); } @@ -62,8 +62,8 @@ struct acosh_fun { * @return Inverse hyperbolic cosine of the argument. */ template - static inline auto fun(const T& x) { - return acosh(x); + static inline auto fun(T&& x) { + return acosh(std::forward(x)); } }; @@ -78,8 +78,8 @@ struct acosh_fun { * @return Elementwise acosh of members of container. */ template * = nullptr> -inline auto acosh(const T& x) { - return apply_scalar_unary::apply(x); +inline auto acosh(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } /** @@ -94,8 +94,9 @@ inline auto acosh(const T& x) { */ template * = nullptr> -inline auto acosh(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto acosh(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } namespace internal { diff --git a/stan/math/prim/fun/asin.hpp b/stan/math/prim/fun/asin.hpp index f620a24d2af..f34b3b24dda 100644 --- a/stan/math/prim/fun/asin.hpp +++ b/stan/math/prim/fun/asin.hpp @@ -24,7 +24,7 @@ namespace math { * @return arc sine of the argument */ template * = nullptr> -inline auto asin(const T x) { +inline auto asin(T&& x) { return std::asin(x); } @@ -36,7 +36,7 @@ inline auto asin(const T x) { * @return arc sine of the argument */ template * = nullptr> -inline auto asin(const T x) { +inline auto asin(T&& x) { return std::asin(x); } @@ -49,8 +49,12 @@ inline auto asin(const T x) { */ struct asin_fun { template - static inline auto fun(const T& x) { - return asin(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::asin(x); + } else { + return asin(std::forward(x)); + } } }; @@ -63,8 +67,9 @@ struct asin_fun { * @return Arcsine of each variable in the container, in radians. */ template * = nullptr> -inline auto asin(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto asin(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -77,9 +82,9 @@ inline auto asin(const Container& x) { */ template * = nullptr> -inline auto asin(const Container& x) { +inline auto asin(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().asin(); }); + std::forward(x), [](auto&& v) { return v.array().asin(); }); } namespace internal { diff --git a/stan/math/prim/fun/asinh.hpp b/stan/math/prim/fun/asinh.hpp index ab72065efae..e8ab6597310 100644 --- a/stan/math/prim/fun/asinh.hpp +++ b/stan/math/prim/fun/asinh.hpp @@ -27,7 +27,7 @@ namespace math { * @return hyperbolic arc sine of the argument */ template * = nullptr> -inline auto asinh(const T x) { +inline auto asinh(T&& x) { return std::asinh(x); } @@ -39,7 +39,7 @@ inline auto asinh(const T x) { * @return hyperbolic arc sine of the argument */ template * = nullptr> -inline auto asinh(const T x) { +inline auto asinh(T&& x) { return std::asinh(x); } @@ -52,8 +52,12 @@ inline auto asinh(const T x) { */ struct asinh_fun { template - static inline auto fun(const T& x) { - return asinh(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::asinh(x); + } else { + return asinh(std::forward(x)); + } } }; @@ -66,8 +70,8 @@ struct asinh_fun { * @return Inverse hyperbolic sine of each value in the container. */ template * = nullptr> -inline auto asinh(const T& x) { - return apply_scalar_unary::apply(x); +inline auto asinh(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } /** @@ -80,8 +84,9 @@ inline auto asinh(const T& x) { */ template * = nullptr> -inline auto asinh(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto asinh(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } namespace internal { diff --git a/stan/math/prim/fun/atan.hpp b/stan/math/prim/fun/atan.hpp index 9e7099b7d43..c2c07d631f5 100644 --- a/stan/math/prim/fun/atan.hpp +++ b/stan/math/prim/fun/atan.hpp @@ -22,7 +22,7 @@ namespace math { * @return arc tangent of the argument */ template * = nullptr> -inline auto atan(const T x) { +inline auto atan(T&& x) { return std::atan(x); } @@ -34,7 +34,7 @@ inline auto atan(const T x) { * @return arc tangent of the argument */ template * = nullptr> -inline auto atan(const T x) { +inline auto atan(T&& x) { return std::atan(x); } @@ -47,8 +47,12 @@ inline auto atan(const T x) { */ struct atan_fun { template - static inline auto fun(const T& x) { - return atan(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::atan(x); + } else { + return atan(std::forward(x)); + } } }; @@ -61,8 +65,9 @@ struct atan_fun { * @return Arctan of each value in x, in radians. */ template * = nullptr> -inline auto atan(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto atan(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -75,9 +80,9 @@ inline auto atan(const Container& x) { */ template * = nullptr> -inline auto atan(const Container& x) { +inline auto atan(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().atan(); }); + std::forward(x), [](auto&& v) { return v.array().atan(); }); } namespace internal { diff --git a/stan/math/prim/fun/atan2.hpp b/stan/math/prim/fun/atan2.hpp index 7909afdf0d4..54b50d551cd 100644 --- a/stan/math/prim/fun/atan2.hpp +++ b/stan/math/prim/fun/atan2.hpp @@ -36,9 +36,13 @@ double atan2(T1 y, T2 x) { */ template * = nullptr, require_all_not_var_matrix_t* = nullptr> -inline auto atan2(const T1& a, const T2& b) { +inline auto atan2(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return atan2(c, d); }, a, b); + [](auto&& c, auto&& d) { + return atan2(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/atanh.hpp b/stan/math/prim/fun/atanh.hpp index fdf6c4df9b5..e68cdf17033 100644 --- a/stan/math/prim/fun/atanh.hpp +++ b/stan/math/prim/fun/atanh.hpp @@ -25,7 +25,7 @@ namespace math { * @throw std::domain_error If argument is not in [-1, 1]. */ template * = nullptr> -inline double atanh(const T x) { +inline double atanh(T&& x) { if (is_nan(x)) { return x; } else { @@ -45,7 +45,7 @@ inline double atanh(const T x) { * @throw std::domain_error If argument is not in [-1, 1]. */ template * = nullptr> -inline auto atanh(const T x) { +inline auto atanh(T&& x) { return std::atanh(x); } @@ -61,8 +61,8 @@ struct atanh_fun { * @return Inverse hyperbolic tangent of the argument. */ template - static inline auto fun(const T& x) { - return atanh(x); + static inline auto fun(T&& x) { + return atanh(std::forward(x)); } }; @@ -77,8 +77,8 @@ struct atanh_fun { * @return Elementwise atanh of members of container. */ template * = nullptr> -inline auto atanh(const T& x) { - return apply_scalar_unary::apply(x); +inline auto atanh(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } /** @@ -93,8 +93,9 @@ inline auto atanh(const T& x) { */ template * = nullptr> -inline auto atanh(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto atanh(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } namespace internal { diff --git a/stan/math/prim/fun/bessel_first_kind.hpp b/stan/math/prim/fun/bessel_first_kind.hpp index e28cd8e3e0c..ba76708d233 100644 --- a/stan/math/prim/fun/bessel_first_kind.hpp +++ b/stan/math/prim/fun/bessel_first_kind.hpp @@ -53,10 +53,13 @@ inline T2 bessel_first_kind(int v, const T2 z) { */ template * = nullptr, require_not_var_matrix_t* = nullptr> -inline auto bessel_first_kind(const T1& a, const T2& b) { +inline auto bessel_first_kind(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return bessel_first_kind(c, d); }, a, - b); + [](auto&& c, auto&& d) { + return bessel_first_kind(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/bessel_second_kind.hpp b/stan/math/prim/fun/bessel_second_kind.hpp index e7a711c24e4..377badca7f8 100644 --- a/stan/math/prim/fun/bessel_second_kind.hpp +++ b/stan/math/prim/fun/bessel_second_kind.hpp @@ -53,10 +53,13 @@ inline T2 bessel_second_kind(int v, const T2 z) { * @return Bessel second kind function applied to the two inputs. */ template * = nullptr> -inline auto bessel_second_kind(const T1& a, const T2& b) { +inline auto bessel_second_kind(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return bessel_second_kind(c, d); }, a, - b); + [](auto&& c, auto&& d) { + return bessel_second_kind(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/beta.hpp b/stan/math/prim/fun/beta.hpp index 969ce5e0efc..fefcf44b479 100644 --- a/stan/math/prim/fun/beta.hpp +++ b/stan/math/prim/fun/beta.hpp @@ -67,9 +67,12 @@ inline return_type_t beta(const T1 a, const T2 b) { */ template * = nullptr, require_all_not_var_matrix_t* = nullptr> -inline auto beta(const T1& a, const T2& b) { +inline auto beta(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return beta(c, d); }, a, b); + [](auto&& c, auto&& d) { + return beta(std::forward(c), std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/binary_log_loss.hpp b/stan/math/prim/fun/binary_log_loss.hpp index 2fba8a37b8d..ba097e56574 100644 --- a/stan/math/prim/fun/binary_log_loss.hpp +++ b/stan/math/prim/fun/binary_log_loss.hpp @@ -44,9 +44,13 @@ inline T binary_log_loss(int y, const T& y_hat) { */ template * = nullptr, require_not_var_matrix_t* = nullptr> -inline auto binary_log_loss(const T1& a, const T2& b) { +inline auto binary_log_loss(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return binary_log_loss(c, d); }, a, b); + [](auto&& c, auto&& d) { + return binary_log_loss(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/binomial_coefficient_log.hpp b/stan/math/prim/fun/binomial_coefficient_log.hpp index 986807a55f8..f9c70facedc 100644 --- a/stan/math/prim/fun/binomial_coefficient_log.hpp +++ b/stan/math/prim/fun/binomial_coefficient_log.hpp @@ -161,12 +161,13 @@ inline return_type_t binomial_coefficient_log(const T_n n, * @return Binomial coefficient log function applied to the two inputs. */ template * = nullptr> -inline auto binomial_coefficient_log(const T1& a, const T2& b) { +inline auto binomial_coefficient_log(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { - return binomial_coefficient_log(c, d); + [](auto&& c, auto&& d) { + return binomial_coefficient_log(std::forward(c), + std::forward(d)); }, - a, b); + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/cbrt.hpp b/stan/math/prim/fun/cbrt.hpp index 090105f25aa..e4d8e0e0cff 100644 --- a/stan/math/prim/fun/cbrt.hpp +++ b/stan/math/prim/fun/cbrt.hpp @@ -8,6 +8,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto cbrt(T&& x) { + return std::cbrt(x); +} + /** * Structure to wrap `cbrt()` so it can be vectorized. * @@ -17,9 +22,12 @@ namespace math { */ struct cbrt_fun { template - static inline auto fun(const T& x) { - using std::cbrt; - return cbrt(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::cbrt(x); + } else { + return cbrt(std::forward(x)); + } } }; @@ -33,8 +41,9 @@ struct cbrt_fun { */ template < typename T, require_not_var_matrix_t* = nullptr, - require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto cbrt(const T& x) { + require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto cbrt(T&& x) { return apply_scalar_unary::apply(x); } diff --git a/stan/math/prim/fun/ceil.hpp b/stan/math/prim/fun/ceil.hpp index c257837250e..0e4d4d55fc2 100644 --- a/stan/math/prim/fun/ceil.hpp +++ b/stan/math/prim/fun/ceil.hpp @@ -10,6 +10,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto ceil(T&& x) { + return std::ceil(x); +} + /** * Structure to wrap `ceil()` so it can be vectorized. * @@ -19,9 +24,12 @@ namespace math { */ struct ceil_fun { template - static inline auto fun(const T& x) { - using std::ceil; - return ceil(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::ceil(x); + } else { + return ceil(std::forward(x)); + } } }; @@ -36,9 +44,11 @@ struct ceil_fun { template * = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< - Container>* = nullptr> -inline auto ceil(const Container& x) { - return apply_scalar_unary::apply(x); + Container>* = nullptr, + require_container_t* = nullptr> +inline auto ceil(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -52,9 +62,10 @@ inline auto ceil(const Container& x) { template * = nullptr, require_not_var_matrix_t* = nullptr> -inline auto ceil(const Container& x) { +inline auto ceil(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().ceil(); }); + std::forward(x), + [](const auto& v) { return v.array().ceil(); }); } } // namespace math diff --git a/stan/math/prim/fun/choose.hpp b/stan/math/prim/fun/choose.hpp index 92528cc676b..05ac3911b13 100644 --- a/stan/math/prim/fun/choose.hpp +++ b/stan/math/prim/fun/choose.hpp @@ -49,9 +49,13 @@ inline int choose(int n, int k) { * @return Binomial coefficient function applied to the two inputs. */ template * = nullptr> -inline auto choose(const T1& a, const T2& b) { +inline auto choose(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return choose(c, d); }, a, b); + [](auto&& c, auto&& d) { + return choose(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/cos.hpp b/stan/math/prim/fun/cos.hpp index 0a3b044ccdc..dd2b951ad6d 100644 --- a/stan/math/prim/fun/cos.hpp +++ b/stan/math/prim/fun/cos.hpp @@ -46,8 +46,12 @@ inline auto cos(const T x) { */ struct cos_fun { template - static inline auto fun(const T& x) { - return cos(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::cos(x); + } else { + return cos(std::forward(x)); + } } }; @@ -60,8 +64,9 @@ struct cos_fun { * @return Cosine of each value in x. */ template * = nullptr> -inline auto cos(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto cos(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -74,9 +79,10 @@ inline auto cos(const Container& x) { */ template * = nullptr> -inline auto cos(const Container& x) { +inline auto cos(Container&& x) { return apply_vector_unary::apply( - x, [&](const auto& v) { return v.array().cos(); }); + std::forward(x), + [&](const auto& v) { return v.array().cos(); }); } namespace internal { diff --git a/stan/math/prim/fun/cosh.hpp b/stan/math/prim/fun/cosh.hpp index ae60c233a68..2b9fb2dec17 100644 --- a/stan/math/prim/fun/cosh.hpp +++ b/stan/math/prim/fun/cosh.hpp @@ -20,7 +20,7 @@ namespace math { * @return hyperbolic cosine of the argument */ template * = nullptr> -inline auto cosh(const T x) { +inline auto cosh(T&& x) { return std::cosh(x); } @@ -32,7 +32,7 @@ inline auto cosh(const T x) { * @return hyperbolic cosine of the argument */ template * = nullptr> -inline auto cosh(const T x) { +inline auto cosh(T&& x) { return std::cosh(x); } @@ -45,8 +45,12 @@ inline auto cosh(const T x) { */ struct cosh_fun { template - static inline auto fun(const T& x) { - return cosh(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::cosh(x); + } else { + return cosh(std::forward(x)); + } } }; @@ -59,8 +63,9 @@ struct cosh_fun { * @return Hyberbolic cosine of x. */ template * = nullptr> -inline auto cosh(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto cosh(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -73,9 +78,9 @@ inline auto cosh(const Container& x) { */ template * = nullptr> -inline auto cosh(const Container& x) { +inline auto cosh(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().cosh(); }); + std::forward(x), [](auto&& v) { return v.array().cosh(); }); } namespace internal { diff --git a/stan/math/prim/fun/digamma.hpp b/stan/math/prim/fun/digamma.hpp index 05032782e8c..cfcc1529888 100644 --- a/stan/math/prim/fun/digamma.hpp +++ b/stan/math/prim/fun/digamma.hpp @@ -44,7 +44,8 @@ namespace math { * @param[in] x argument * @return derivative of log gamma function at argument */ -inline double digamma(double x) { +template * = nullptr> +inline double digamma(T&& x) { return boost::math::digamma(x, boost_policy_t<>()); } @@ -58,8 +59,8 @@ inline double digamma(double x) { */ struct digamma_fun { template - static inline auto fun(const T& x) { - return digamma(x); + static inline auto fun(T&& x) { + return digamma(std::forward(x)); } }; @@ -73,9 +74,10 @@ struct digamma_fun { */ template * = nullptr, + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> -inline auto digamma(const T& x) { - return apply_scalar_unary::apply(x); +inline auto digamma(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/erf.hpp b/stan/math/prim/fun/erf.hpp index 9f3526bcafa..67fa1e20d71 100644 --- a/stan/math/prim/fun/erf.hpp +++ b/stan/math/prim/fun/erf.hpp @@ -8,6 +8,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto erf(T&& x) { + return std::erf(x); +} + /** * Structure to wrap `erf()` so it can be vectorized. * @@ -17,9 +22,12 @@ namespace math { */ struct erf_fun { template - static inline auto fun(const T& x) { - using std::erf; - return erf(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::erf(x); + } else { + return erf(std::forward(x)); + } } }; @@ -34,9 +42,9 @@ struct erf_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto erf(const T& x) { - return apply_scalar_unary::apply(x); + require_not_var_matrix_t* = nullptr, require_container_t* = nullptr> +inline auto erf(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/erfc.hpp b/stan/math/prim/fun/erfc.hpp index a9599b42b2c..4e503e6ad65 100644 --- a/stan/math/prim/fun/erfc.hpp +++ b/stan/math/prim/fun/erfc.hpp @@ -8,6 +8,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto erfc(T&& x) { + return std::erfc(x); +} + /** * Structure to wrap the `erfc()` * so that it can be vectorized. @@ -18,9 +23,12 @@ namespace math { */ struct erfc_fun { template - static inline auto fun(const T& x) { - using std::erfc; - return erfc(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::erfc(x); + } else { + return erfc(std::forward(x)); + } } }; @@ -35,9 +43,9 @@ struct erfc_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto erfc(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> +inline auto erfc(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/exp.hpp b/stan/math/prim/fun/exp.hpp index d12d82cb556..0e5681fdd9d 100644 --- a/stan/math/prim/fun/exp.hpp +++ b/stan/math/prim/fun/exp.hpp @@ -21,7 +21,7 @@ namespace math { * @return natural exponentiation of specified number */ template * = nullptr> -inline auto exp(const T x) { +inline auto exp(T&& x) { return std::exp(x); } @@ -36,7 +36,7 @@ inline auto exp(const T x) { * branch cut details */ template * = nullptr> -inline auto exp(const T x) { +inline auto exp(T&& x) { return std::exp(x); } @@ -53,8 +53,12 @@ struct exp_fun { * @return Exponential of argument. */ template - static inline auto fun(const T& x) { - return exp(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::exp(x); + } else { + return exp(std::forward(x)); + } } }; @@ -68,8 +72,9 @@ struct exp_fun { * @return Elementwise application of exponentiation to the argument. */ template * = nullptr> -inline auto exp(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto exp(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -82,9 +87,9 @@ inline auto exp(const Container& x) { */ template * = nullptr> -inline auto exp(const Container& x) { +inline auto exp(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().exp(); }); + std::forward(x), [](auto&& v) { return v.array().exp(); }); } namespace internal { diff --git a/stan/math/prim/fun/exp2.hpp b/stan/math/prim/fun/exp2.hpp index f5f491cb926..1528a6fb68b 100644 --- a/stan/math/prim/fun/exp2.hpp +++ b/stan/math/prim/fun/exp2.hpp @@ -8,6 +8,10 @@ namespace stan { namespace math { +template * = nullptr> +inline auto exp2(T&& x) { + return std::exp2(x); +} /** * Structure to wrap `exp2()` so it can be vectorized. */ @@ -20,9 +24,12 @@ struct exp2_fun { * @return Base two exponent of the argument. */ template - static inline auto fun(const T& x) { - using std::exp2; - return exp2(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::exp2(x); + } else { + return exp2(std::forward(x)); + } } }; @@ -38,9 +45,9 @@ struct exp2_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto exp2(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> +inline auto exp2(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/expm1.hpp b/stan/math/prim/fun/expm1.hpp index 62d6cab97f7..ae4b269eddf 100644 --- a/stan/math/prim/fun/expm1.hpp +++ b/stan/math/prim/fun/expm1.hpp @@ -8,6 +8,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto expm1(T&& x) { + return std::expm1(x); +} + /** * Structure to wrap `expm1()` so that it can be vectorized. * @@ -17,9 +22,12 @@ namespace math { */ struct expm1_fun { template - static inline auto fun(const T& x) { - using std::expm1; - return expm1(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::expm1(x); + } else { + return expm1(std::forward(x)); + } } }; @@ -35,9 +43,9 @@ struct expm1_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto expm1(const T& x) { - return apply_scalar_unary::apply(x); + require_not_var_matrix_t* = nullptr, require_container_t* = nullptr> +inline auto expm1(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/fabs.hpp b/stan/math/prim/fun/fabs.hpp index 71a1d521656..5c2666f1c32 100644 --- a/stan/math/prim/fun/fabs.hpp +++ b/stan/math/prim/fun/fabs.hpp @@ -11,12 +11,12 @@ namespace stan { namespace math { template * = nullptr> -inline auto fabs(T x) { +inline auto fabs(T&& x) { return std::abs(x); } -template * = nullptr> -inline auto fabs(T x) { +template * = nullptr> +inline auto fabs(T&& x) { return std::hypot(x.real(), x.imag()); } @@ -29,8 +29,12 @@ inline auto fabs(T x) { */ struct fabs_fun { template - static inline auto fun(const T& x) { - return fabs(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::fabs(x); + } else { + return fabs(std::forward(x)); + } } }; @@ -47,9 +51,11 @@ template * = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< Container>* = nullptr, - require_not_stan_scalar_t* = nullptr> -inline auto fabs(const Container& x) { - return apply_scalar_unary::apply(x); + require_not_stan_scalar_t* = nullptr, + require_container_t* = nullptr> +inline auto fabs(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -62,9 +68,9 @@ inline auto fabs(const Container& x) { */ template * = nullptr> -inline auto fabs(const Container& x) { +inline auto fabs(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().abs(); }); + std::forward(x), [](auto&& v) { return v.array().abs(); }); } } // namespace math diff --git a/stan/math/prim/fun/falling_factorial.hpp b/stan/math/prim/fun/falling_factorial.hpp index 0a79f0c4a7c..4040a53150a 100644 --- a/stan/math/prim/fun/falling_factorial.hpp +++ b/stan/math/prim/fun/falling_factorial.hpp @@ -80,10 +80,13 @@ inline return_type_t falling_factorial(const T& x, int n) { */ template * = nullptr, require_all_not_var_matrix_t* = nullptr> -inline auto falling_factorial(const T1& a, const T2& b) { +inline auto falling_factorial(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return falling_factorial(c, d); }, a, - b); + [](auto&& c, auto&& d) { + return falling_factorial(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/fdim.hpp b/stan/math/prim/fun/fdim.hpp index 4ed2d8231c7..c940a79ffbf 100644 --- a/stan/math/prim/fun/fdim.hpp +++ b/stan/math/prim/fun/fdim.hpp @@ -35,9 +35,12 @@ inline double fdim(T1 x, T2 y) { * @return Fdim function applied to the two inputs. */ template * = nullptr> -inline auto fdim(const T1& a, const T2& b) { +inline auto fdim(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return fdim(c, d); }, a, b); + [](auto&& c, auto&& d) { + return fdim(std::forward(c), std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/floor.hpp b/stan/math/prim/fun/floor.hpp index 3845bee34b2..63a5385d3bd 100644 --- a/stan/math/prim/fun/floor.hpp +++ b/stan/math/prim/fun/floor.hpp @@ -11,12 +11,12 @@ namespace stan { namespace math { template * = nullptr> -inline auto floor(const T x) { +inline auto floor(T&& x) { return std::floor(x); } template * = nullptr> -inline auto floor(const T x) { +inline auto floor(T&& x) { return std::floor(x); } /** @@ -28,8 +28,12 @@ inline auto floor(const T x) { */ struct floor_fun { template - static inline auto fun(const T& x) { - return floor(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::floor(x); + } else { + return floor(std::forward(x)); + } } }; @@ -42,8 +46,9 @@ struct floor_fun { * @return Greatest integer <= each value in x. */ template * = nullptr> -inline auto floor(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto floor(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -57,9 +62,9 @@ inline auto floor(const Container& x) { template * = nullptr, require_not_var_matrix_t* = nullptr> -inline auto floor(const Container& x) { +inline auto floor(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().floor(); }); + std::forward(x), [](auto&& v) { return v.array().floor(); }); } } // namespace math diff --git a/stan/math/prim/fun/fmax.hpp b/stan/math/prim/fun/fmax.hpp index 43790df1272..77c0319ede5 100644 --- a/stan/math/prim/fun/fmax.hpp +++ b/stan/math/prim/fun/fmax.hpp @@ -33,9 +33,12 @@ inline double fmax(T1 x, T2 y) { * @return fmax function applied to the two inputs. */ template * = nullptr> -inline auto fmax(const T1& a, const T2& b) { +inline auto fmax(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return fmax(c, d); }, a, b); + [](auto&& c, auto&& d) { + return fmax(std::forward(c), std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/fmin.hpp b/stan/math/prim/fun/fmin.hpp index c7011c00a2c..5b2ffe63643 100644 --- a/stan/math/prim/fun/fmin.hpp +++ b/stan/math/prim/fun/fmin.hpp @@ -33,9 +33,12 @@ inline double fmin(T1 x, T2 y) { * @return fmin function applied to the two inputs. */ template * = nullptr> -inline auto fmin(const T1& a, const T2& b) { +inline auto fmin(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return fmin(c, d); }, a, b); + [](auto&& c, auto&& d) { + return fmin(std::forward(c), std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/fmod.hpp b/stan/math/prim/fun/fmod.hpp index 53c575c12d8..a6c53d99337 100644 --- a/stan/math/prim/fun/fmod.hpp +++ b/stan/math/prim/fun/fmod.hpp @@ -34,13 +34,12 @@ inline double fmod(const T1& a, const T2& b) { * @return fmod function applied to the two inputs. */ template * = nullptr> -inline auto fmod(const T1& a, const T2& b) { +inline auto fmod(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { - using std::fmod; - return fmod(c, d); + [](auto&& c, auto&& d) { + return fmod(std::forward(c), std::forward(d)); }, - a, b); + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/gamma_p.hpp b/stan/math/prim/fun/gamma_p.hpp index de21249ca37..59ca71a2e42 100644 --- a/stan/math/prim/fun/gamma_p.hpp +++ b/stan/math/prim/fun/gamma_p.hpp @@ -87,9 +87,13 @@ inline double gamma_p(double z, double a) { * @return gamma_p function applied to the two inputs. */ template * = nullptr> -inline auto gamma_p(const T1& a, const T2& b) { +inline auto gamma_p(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return gamma_p(c, d); }, a, b); + [](auto&& c, auto&& d) { + return gamma_p(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/gamma_q.hpp b/stan/math/prim/fun/gamma_q.hpp index 2b4e2494305..17b9ceb92da 100644 --- a/stan/math/prim/fun/gamma_q.hpp +++ b/stan/math/prim/fun/gamma_q.hpp @@ -65,9 +65,13 @@ inline double gamma_q(double x, double a) { return boost::math::gamma_q(x, a); } * @return gamma_q function applied to the two inputs. */ template * = nullptr> -inline auto gamma_q(const T1& a, const T2& b) { +inline auto gamma_q(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return gamma_q(c, d); }, a, b); + [](auto&& c, auto&& d) { + return gamma_q(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/hypot.hpp b/stan/math/prim/fun/hypot.hpp index 07fe51d1857..c074b730f17 100644 --- a/stan/math/prim/fun/hypot.hpp +++ b/stan/math/prim/fun/hypot.hpp @@ -39,9 +39,13 @@ inline double hypot(T1 x, T2 y) { template * = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< T1, T2>* = nullptr> -inline auto hypot(const T1& a, const T2& b) { +inline auto hypot(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return hypot(c, d); }, a, b); + [](auto&& c, auto&& d) { + return hypot(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/inc_beta.hpp b/stan/math/prim/fun/inc_beta.hpp index a1055f86dd0..2755f35e717 100644 --- a/stan/math/prim/fun/inc_beta.hpp +++ b/stan/math/prim/fun/inc_beta.hpp @@ -44,10 +44,10 @@ inline double inc_beta(double a, double b, double x) { template * = nullptr, require_all_not_var_matrix_t* = nullptr> -inline auto inc_beta(const T1& a, const T2& b, const T3& c) { - return apply_scalar_ternary([](const auto& d, const auto& e, - const auto& f) { return inc_beta(d, e, f); }, - a, b, c); +inline auto inc_beta(T1&& a, T2&& b, T3&& c) { + return apply_scalar_ternary( + [](auto&& d, auto&& e, auto&& f) { return inc_beta(d, e, f); }, + std::forward(a), std::forward(b), std::forward(c)); } } // namespace math diff --git a/stan/math/prim/fun/inv.hpp b/stan/math/prim/fun/inv.hpp index fe09a75e6df..fee504e58c0 100644 --- a/stan/math/prim/fun/inv.hpp +++ b/stan/math/prim/fun/inv.hpp @@ -9,6 +9,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto inv(T x) { + return 1.0 / x; +} + /** * Structure to wrap 1.0 / x so that it can be vectorized. * @@ -18,7 +23,7 @@ namespace math { */ struct inv_fun { template - static inline auto fun(const T& x) { + static inline auto fun(T&& x) { return 1.0 / x; } }; @@ -33,9 +38,10 @@ struct inv_fun { */ template < typename T, require_not_container_st* = nullptr, - require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto inv(const T& x) { - return apply_scalar_unary::apply(x); + require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto inv(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } /** @@ -50,9 +56,10 @@ template * = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< Container>* = nullptr> -inline auto inv(const Container& x) { +inline auto inv(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().inverse(); }); + std::forward(x), + [](const auto& v) { return v.array().inverse(); }); } } // namespace math diff --git a/stan/math/prim/fun/inv_Phi.hpp b/stan/math/prim/fun/inv_Phi.hpp index 0ec72de8062..5385819ba8c 100644 --- a/stan/math/prim/fun/inv_Phi.hpp +++ b/stan/math/prim/fun/inv_Phi.hpp @@ -160,8 +160,8 @@ inline double inv_Phi(double p) { */ struct inv_Phi_fun { template - static inline auto fun(const T& x) { - return inv_Phi(x); + static inline auto fun(T&& x) { + return inv_Phi(std::forward(x)); } }; @@ -176,9 +176,9 @@ struct inv_Phi_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto inv_Phi(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> +inline auto inv_Phi(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/inv_cloglog.hpp b/stan/math/prim/fun/inv_cloglog.hpp index f197d49c24e..aaf9576cfe6 100644 --- a/stan/math/prim/fun/inv_cloglog.hpp +++ b/stan/math/prim/fun/inv_cloglog.hpp @@ -77,8 +77,8 @@ inline auto inv_cloglog(const T& x) { */ struct inv_cloglog_fun { template - static inline auto fun(const T& x) { - return inv_cloglog(x); + static inline auto fun(T&& x) { + return inv_cloglog(std::forward(x)); } }; @@ -90,8 +90,9 @@ struct inv_cloglog_fun { * @return 1 - exp(-exp()) applied to each value in x. */ template * = nullptr> -inline auto inv_cloglog(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto inv_cloglog(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -104,9 +105,10 @@ inline auto inv_cloglog(const Container& x) { */ template * = nullptr> -inline auto inv_cloglog(const Container& x) { +inline auto inv_cloglog(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return 1 - (-v.array().exp()).exp(); }); + std::forward(x), + [](auto&& v) { return 1 - (-v.array().exp()).exp(); }); } } // namespace math diff --git a/stan/math/prim/fun/inv_erfc.hpp b/stan/math/prim/fun/inv_erfc.hpp index 4eca9e1b8cd..81b4882d3ae 100644 --- a/stan/math/prim/fun/inv_erfc.hpp +++ b/stan/math/prim/fun/inv_erfc.hpp @@ -30,8 +30,8 @@ inline auto inv_erfc(const T& x) { */ struct inv_erfc_fun { template - static inline auto fun(const T& x) { - return inv_erfc(x); + static inline auto fun(T&& x) { + return inv_erfc(std::forward(x)); } }; @@ -46,10 +46,10 @@ struct inv_erfc_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr, + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr, require_not_arithmetic_t* = nullptr> -inline auto inv_erfc(const T& x) { - return apply_scalar_unary::apply(x); +inline auto inv_erfc(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/inv_inc_beta.hpp b/stan/math/prim/fun/inv_inc_beta.hpp index 168431ae32c..93ecf96cb2a 100644 --- a/stan/math/prim/fun/inv_inc_beta.hpp +++ b/stan/math/prim/fun/inv_inc_beta.hpp @@ -46,12 +46,10 @@ inline double inv_inc_beta(double a, double b, double p) { */ template * = nullptr> -inline auto inv_inc_beta(const T1& a, const T2& b, const T3& c) { +inline auto inv_inc_beta(T1&& a, T2&& b, T3&& c) { return apply_scalar_ternary( - [](const auto& d, const auto& e, const auto& f) { - return inv_inc_beta(d, e, f); - }, - a, b, c); + [](auto&& d, auto&& e, auto&& f) { return inv_inc_beta(d, e, f); }, + std::forward(a), std::forward(b), std::forward(c)); } } // namespace math diff --git a/stan/math/prim/fun/inv_logit.hpp b/stan/math/prim/fun/inv_logit.hpp index 08f2a940a7f..357871ed2d2 100644 --- a/stan/math/prim/fun/inv_logit.hpp +++ b/stan/math/prim/fun/inv_logit.hpp @@ -48,15 +48,13 @@ namespace math { * @param a Argument. * @return Inverse logit of argument. */ -inline double inv_logit(double a) { +template * = nullptr> +inline double inv_logit(T&& a) { if (a < 0) { double exp_a = std::exp(a); - if (a < LOG_EPSILON) { - return exp_a; - } return exp_a / (1.0 + exp_a); } - return inv(1 + std::exp(-a)); + return inv(1.0 + std::exp(-a)); } /** diff --git a/stan/math/prim/fun/inv_sqrt.hpp b/stan/math/prim/fun/inv_sqrt.hpp index 00fa616a45f..e0518cf599d 100644 --- a/stan/math/prim/fun/inv_sqrt.hpp +++ b/stan/math/prim/fun/inv_sqrt.hpp @@ -31,8 +31,8 @@ inline auto inv_sqrt(const T x) { */ struct inv_sqrt_fun { template - static inline auto fun(const T& x) { - return inv_sqrt(x); + static inline auto fun(T&& x) { + return inv_sqrt(std::forward(x)); } }; @@ -45,8 +45,9 @@ struct inv_sqrt_fun { * @return inverse square root of each value in x. */ template * = nullptr> -inline auto inv_sqrt(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto inv_sqrt(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -59,14 +60,16 @@ inline auto inv_sqrt(const Container& x) { */ template * = nullptr, require_container_bt* = nullptr> -inline auto inv_sqrt(const Container& x) { +inline auto inv_sqrt(Container&& x) { // Eigen 3.4.0 has precision issues on ARM64 with vectorised rsqrt // Resolved in current master branch, below can be removed on next release #ifdef __aarch64__ - return apply_scalar_unary::apply(x); + return apply_scalar_unary::apply( + std::forward(x)); #else return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().rsqrt(); }); + std::forward(x), + [](const auto& v) { return v.array().rsqrt(); }); #endif } diff --git a/stan/math/prim/fun/inv_square.hpp b/stan/math/prim/fun/inv_square.hpp index 0793e054c3d..b413b995d17 100644 --- a/stan/math/prim/fun/inv_square.hpp +++ b/stan/math/prim/fun/inv_square.hpp @@ -9,6 +9,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto inv_square(T&& x) { + return inv(square(x)); +} + /** * Returns `1 / square(x)`. * @@ -19,9 +24,10 @@ namespace math { template * = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< - Container>* = nullptr> -inline auto inv_square(const Container& x) { - return inv(square(x)); + Container>* = nullptr, + require_container_t* = nullptr> +inline auto inv_square(Container&& x) { + return inv(square(std::forward(x))); } /** @@ -34,9 +40,10 @@ inline auto inv_square(const Container& x) { */ template * = nullptr> -inline auto inv_square(const Container& x) { +inline auto inv_square(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().square().inverse(); }); + std::forward(x), + [](auto&& v) { return v.array().square().inverse(); }); } } // namespace math diff --git a/stan/math/prim/fun/lambert_w.hpp b/stan/math/prim/fun/lambert_w.hpp index 2af6cf9e55f..bd89070eb6e 100644 --- a/stan/math/prim/fun/lambert_w.hpp +++ b/stan/math/prim/fun/lambert_w.hpp @@ -48,8 +48,8 @@ namespace internal { */ struct lambert_w0_fun { template - static inline auto fun(const T& x) { - return lambert_w0(x); + static inline auto fun(T&& x) { + return lambert_w0(std::forward(x)); } }; @@ -64,8 +64,8 @@ struct lambert_w0_fun { */ struct lambert_wm1_fun { template - static inline auto fun(const T& x) { - return lambert_wm1(x); + static inline auto fun(T&& x) { + return lambert_wm1(std::forward(x)); } }; } // namespace internal @@ -79,9 +79,11 @@ struct lambert_wm1_fun { * @throw std::domain_error if x is less than or equal to `-e^(-1)` */ template * = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto lambert_w0(const T& x) { - return apply_scalar_unary::apply(x); + require_not_var_matrix_t* = nullptr, + require_container_t* = nullptr> +inline auto lambert_w0(T&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -94,9 +96,11 @@ inline auto lambert_w0(const T& x) { * than or equal to 0 */ template * = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto lambert_wm1(const T& x) { - return apply_scalar_unary::apply(x); + require_not_var_matrix_t* = nullptr, + require_container_t* = nullptr> +inline auto lambert_wm1(T&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/lbeta.hpp b/stan/math/prim/fun/lbeta.hpp index 82b4a507bea..5716c290b8c 100644 --- a/stan/math/prim/fun/lbeta.hpp +++ b/stan/math/prim/fun/lbeta.hpp @@ -127,9 +127,13 @@ return_type_t lbeta(const T1 a, const T2 b) { * @return lbeta function applied to the two inputs. */ template * = nullptr> -inline auto lbeta(const T1& a, const T2& b) { +inline auto lbeta(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return lbeta(c, d); }, a, b); + [](auto&& c, auto&& d) { + return lbeta(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/ldexp.hpp b/stan/math/prim/fun/ldexp.hpp index 01f6856032a..4430559ec5b 100644 --- a/stan/math/prim/fun/ldexp.hpp +++ b/stan/math/prim/fun/ldexp.hpp @@ -36,9 +36,13 @@ inline double ldexp(T1 a, int b) { template * = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< T1, T2>* = nullptr> -inline auto ldexp(const T1& a, const T2& b) { +inline auto ldexp(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return ldexp(c, d); }, a, b); + [](auto&& c, auto&& d) { + return ldexp(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/lgamma.hpp b/stan/math/prim/fun/lgamma.hpp index 8c5fec86e79..7b37c5535b0 100644 --- a/stan/math/prim/fun/lgamma.hpp +++ b/stan/math/prim/fun/lgamma.hpp @@ -100,8 +100,8 @@ inline double lgamma(int x) { */ struct lgamma_fun { template - static inline auto fun(const T& x) { - return lgamma(x); + static inline auto fun(T&& x) { + return lgamma(std::forward(x)); } }; @@ -115,9 +115,10 @@ struct lgamma_fun { * @throw std::domain_error if any value is a negative integer or 0. */ template * = nullptr, - require_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto lgamma(const T& x) { - return apply_scalar_unary::apply(x); + require_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto lgamma(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/lmgamma.hpp b/stan/math/prim/fun/lmgamma.hpp index 5d1b946f7e8..9f4381deaf0 100644 --- a/stan/math/prim/fun/lmgamma.hpp +++ b/stan/math/prim/fun/lmgamma.hpp @@ -70,9 +70,13 @@ inline return_type_t lmgamma(int k, T x) { * inputs. */ template * = nullptr> -inline auto lmgamma(const T1& a, const T2& b) { +inline auto lmgamma(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return lmgamma(c, d); }, a, b); + [](auto&& c, auto&& d) { + return lmgamma(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/lmultiply.hpp b/stan/math/prim/fun/lmultiply.hpp index e7de4468f81..8e38dc0695d 100644 --- a/stan/math/prim/fun/lmultiply.hpp +++ b/stan/math/prim/fun/lmultiply.hpp @@ -43,9 +43,13 @@ inline return_type_t lmultiply(const T1 a, const T2 b) { */ template * = nullptr, require_all_not_var_matrix_t* = nullptr> -inline auto lmultiply(const T1& a, const T2& b) { +inline auto lmultiply(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return lmultiply(c, d); }, a, b); + [](auto&& c, auto&& d) { + return lmultiply(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/log.hpp b/stan/math/prim/fun/log.hpp index 8216cee2aa6..1c38ff0d393 100644 --- a/stan/math/prim/fun/log.hpp +++ b/stan/math/prim/fun/log.hpp @@ -24,7 +24,7 @@ namespace math { * @return natural logarithm of the argument */ template * = nullptr> -inline auto log(const T x) { +inline auto log(T&& x) { return std::log(x); } @@ -35,8 +35,8 @@ inline auto log(const T x) { * @param[in] x argument * @return natural logarithm of the argument */ -template * = nullptr> -inline auto log(const T x) { +template * = nullptr> +inline auto log(T&& x) { return std::log(x); } @@ -52,8 +52,12 @@ struct log_fun { * @return Natural log of x. */ template - static inline auto fun(const T& x) { - return log(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::log(x); + } else { + return log(std::forward(x)); + } } }; @@ -67,8 +71,9 @@ struct log_fun { * @return Elementwise application of natural log to the argument. */ template * = nullptr> -inline auto log(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto log(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -81,9 +86,9 @@ inline auto log(const Container& x) { */ template * = nullptr> -inline auto log(const Container& x) { +inline auto log(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().log(); }); + std::forward(x), [](auto&& v) { return v.array().log(); }); } namespace internal { diff --git a/stan/math/prim/fun/log10.hpp b/stan/math/prim/fun/log10.hpp index f7d81343ea5..93d66f0a9bb 100644 --- a/stan/math/prim/fun/log10.hpp +++ b/stan/math/prim/fun/log10.hpp @@ -20,7 +20,7 @@ namespace math { * @return base 10 logarithm of the argument */ template * = nullptr> -inline auto log10(const T x) { +inline auto log10(T&& x) { return std::log10(x); } @@ -32,7 +32,7 @@ inline auto log10(const T x) { * @return base 10 logarithm of the argument */ template * = nullptr> -inline auto log10(const T x) { +inline auto log10(T&& x) { return std::log10(x); } @@ -45,8 +45,12 @@ inline auto log10(const T x) { */ struct log10_fun { template - static inline auto fun(const T& x) { - return log10(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::log10(x); + } else { + return log10(std::forward(x)); + } } }; @@ -58,8 +62,9 @@ struct log10_fun { * @return Log base-10 applied to each value in x. */ template * = nullptr> -inline auto log10(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto log10(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -72,9 +77,9 @@ inline auto log10(const Container& x) { */ template * = nullptr> -inline auto log10(const Container& x) { +inline auto log10(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().log10(); }); + std::forward(x), [](auto&& v) { return v.array().log10(); }); } namespace internal { diff --git a/stan/math/prim/fun/log1m.hpp b/stan/math/prim/fun/log1m.hpp index 702ee7f20fb..d19201cde04 100644 --- a/stan/math/prim/fun/log1m.hpp +++ b/stan/math/prim/fun/log1m.hpp @@ -55,8 +55,8 @@ inline double log1m(double x) { */ struct log1m_fun { template - static inline auto fun(const T& x) { - return log1m(x); + static inline auto fun(T&& x) { + return log1m(std::forward(x)); } }; @@ -69,9 +69,10 @@ struct log1m_fun { */ template < typename T, require_not_var_matrix_t* = nullptr, - require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto log1m(const T& x) { - return apply_scalar_unary::apply(x); + require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto log1m(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/log1m_exp.hpp b/stan/math/prim/fun/log1m_exp.hpp index 89d1a4d6af6..b4d6df49f28 100644 --- a/stan/math/prim/fun/log1m_exp.hpp +++ b/stan/math/prim/fun/log1m_exp.hpp @@ -3,11 +3,11 @@ #include #include +#include #include #include #include #include -#include #include namespace stan { @@ -65,8 +65,8 @@ inline double log1m_exp(double a) { */ struct log1m_exp_fun { template - static inline auto fun(const T& x) { - return log1m_exp(x); + static inline auto fun(T&& x) { + return log1m_exp(std::forward(x)); } }; @@ -79,9 +79,10 @@ struct log1m_exp_fun { */ template < typename T, require_not_var_matrix_t* = nullptr, - require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto log1m_exp(const T& x) { - return apply_scalar_unary::apply(x); + require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto log1m_exp(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/log1m_inv_logit.hpp b/stan/math/prim/fun/log1m_inv_logit.hpp index 0128aa7804e..3cda5cbb44b 100644 --- a/stan/math/prim/fun/log1m_inv_logit.hpp +++ b/stan/math/prim/fun/log1m_inv_logit.hpp @@ -30,28 +30,19 @@ namespace math { \end{cases} \f] * - * @param u argument + * @tparam T An arithmetic type. + * @param uu argument * @return log of one minus the inverse logit of the argument */ -inline double log1m_inv_logit(double u) { - using std::exp; +template * = nullptr> +inline double log1m_inv_logit(T&& uu) { + const auto u = static_cast(uu); if (u > 0.0) { return -u - log1p_exp(-u); // prevent underflow } return -log1p_exp(u); } -/** - * Return the natural logarithm of one minus the inverse logit of - * the specified argument. - * - * @param u argument - * @return log of one minus the inverse logit of the argument - */ -inline double log1m_inv_logit(int u) { - return log1m_inv_logit(static_cast(u)); -} - /** * Structure to wrap log1m_inv_logit() so it can be vectorized. */ @@ -65,8 +56,8 @@ struct log1m_inv_logit_fun { * @return natural log of one minus inverse logit of argument */ template - static inline auto fun(const T& x) { - return log1m_inv_logit(x); + static inline auto fun(T&& x) { + return log1m_inv_logit(std::forward(x)); } }; @@ -81,10 +72,10 @@ struct log1m_inv_logit_fun { * @return Elementwise log1m_inv_logit of members of container. */ template * = nullptr, - require_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline typename apply_scalar_unary::return_t -log1m_inv_logit(const T& x) { - return apply_scalar_unary::apply(x); + require_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto log1m_inv_logit(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/log1p.hpp b/stan/math/prim/fun/log1p.hpp index 3bcbc205a54..5ff607fdebe 100644 --- a/stan/math/prim/fun/log1p.hpp +++ b/stan/math/prim/fun/log1p.hpp @@ -61,8 +61,8 @@ struct log1p_fun { * @return natural log of one plus the argument */ template - static inline auto fun(const T& x) { - return log1p(x); + static inline auto fun(T&& x) { + return log1p(std::forward(x)); } }; @@ -78,9 +78,10 @@ struct log1p_fun { */ template * = nullptr, + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> -inline auto log1p(const T& x) { - return apply_scalar_unary::apply(x); +inline auto log1p(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/log1p_exp.hpp b/stan/math/prim/fun/log1p_exp.hpp index de658ae3885..426c7534a13 100644 --- a/stan/math/prim/fun/log1p_exp.hpp +++ b/stan/math/prim/fun/log1p_exp.hpp @@ -60,8 +60,8 @@ inline double log1p_exp(double a) { */ struct log1p_exp_fun { template - static inline auto fun(const T& x) { - return log1p_exp(x); + static inline auto fun(T&& x) { + return log1p_exp(std::forward(x)); } }; @@ -74,9 +74,10 @@ struct log1p_exp_fun { */ template * = nullptr, + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> -inline auto log1p_exp(const T& x) { - return apply_scalar_unary::apply(x); +inline auto log1p_exp(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/log2.hpp b/stan/math/prim/fun/log2.hpp index 52a0674b8f1..cb74fe38a5a 100644 --- a/stan/math/prim/fun/log2.hpp +++ b/stan/math/prim/fun/log2.hpp @@ -16,6 +16,11 @@ namespace math { */ inline constexpr double log2() { return LOG_TWO; } +template * = nullptr> +inline auto log2(T&& x) { + return std::log2(x); +} + /** * Structure to wrap `log2()` so it can be vectorized. */ @@ -28,9 +33,8 @@ struct log2_fun { * @return base two log of the argument */ template - static inline auto fun(const T& x) { - using std::log2; - return log2(x); + static inline auto fun(T&& x) { + return log2(std::forward(x)); } }; @@ -45,9 +49,10 @@ struct log2_fun { * @return elementwise log2 of container elements */ template * = nullptr, - require_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto log2(const T& x) { - return apply_scalar_unary::apply(x); + require_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto log2(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/log_diff_exp.hpp b/stan/math/prim/fun/log_diff_exp.hpp index a393015582e..463220d5ee7 100644 --- a/stan/math/prim/fun/log_diff_exp.hpp +++ b/stan/math/prim/fun/log_diff_exp.hpp @@ -66,9 +66,13 @@ inline return_type_t log_diff_exp(const T1 x, const T2 y) { * @return log_diff_exp function applied to the two inputs. */ template * = nullptr> -inline auto log_diff_exp(const T1& a, const T2& b) { +inline auto log_diff_exp(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return log_diff_exp(c, d); }, a, b); + [](auto&& c, auto&& d) { + return log_diff_exp(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/log_falling_factorial.hpp b/stan/math/prim/fun/log_falling_factorial.hpp index 7180e42ab6f..f1770d66e70 100644 --- a/stan/math/prim/fun/log_falling_factorial.hpp +++ b/stan/math/prim/fun/log_falling_factorial.hpp @@ -72,10 +72,13 @@ inline return_type_t log_falling_factorial(const T1 x, const T2 n) { * @return log_falling_factorial function applied to the two inputs. */ template * = nullptr> -inline auto log_falling_factorial(const T1& a, const T2& b) { +inline auto log_falling_factorial(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return log_falling_factorial(c, d); }, - a, b); + [](auto&& c, auto&& d) { + return log_falling_factorial(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/log_inv_logit.hpp b/stan/math/prim/fun/log_inv_logit.hpp index d63d8ccf36a..bf2fd125a03 100644 --- a/stan/math/prim/fun/log_inv_logit.hpp +++ b/stan/math/prim/fun/log_inv_logit.hpp @@ -63,8 +63,8 @@ struct log_inv_logit_fun { * @return natural log of inverse logit of argument */ template - static inline auto fun(const T& x) { - return log_inv_logit(x); + static inline auto fun(T&& x) { + return log_inv_logit(std::forward(x)); } }; @@ -80,9 +80,10 @@ struct log_inv_logit_fun { */ template * = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto log_inv_logit(const T& x) { - return apply_scalar_unary::apply(x); + require_not_var_matrix_t* = nullptr, + require_container_t* = nullptr> +inline auto log_inv_logit(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/log_inv_logit_diff.hpp b/stan/math/prim/fun/log_inv_logit_diff.hpp index 9843583d3fc..96bce37601b 100644 --- a/stan/math/prim/fun/log_inv_logit_diff.hpp +++ b/stan/math/prim/fun/log_inv_logit_diff.hpp @@ -52,10 +52,13 @@ inline return_type_t log_inv_logit_diff(const T1& x, const T2& y) { * @return log_inv_logit_diff function applied to the two inputs. */ template * = nullptr> -inline auto log_inv_logit_diff(const T1& a, const T2& b) { +inline auto log_inv_logit_diff(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return log_inv_logit_diff(c, d); }, a, - b); + [](auto&& c, auto&& d) { + return log_inv_logit_diff(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/log_modified_bessel_first_kind.hpp b/stan/math/prim/fun/log_modified_bessel_first_kind.hpp index 7607560a08d..49a17ac36bf 100644 --- a/stan/math/prim/fun/log_modified_bessel_first_kind.hpp +++ b/stan/math/prim/fun/log_modified_bessel_first_kind.hpp @@ -232,12 +232,13 @@ inline return_type_t log_modified_bessel_first_kind( * @return log_modified_bessel_first_kind function applied to the two inputs. */ template * = nullptr> -inline auto log_modified_bessel_first_kind(const T1& a, const T2& b) { +inline auto log_modified_bessel_first_kind(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { - return log_modified_bessel_first_kind(c, d); + [](auto&& c, auto&& d) { + return log_modified_bessel_first_kind(std::forward(c), + std::forward(d)); }, - a, b); + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/log_rising_factorial.hpp b/stan/math/prim/fun/log_rising_factorial.hpp index bff1df3d9e1..24bc73533ea 100644 --- a/stan/math/prim/fun/log_rising_factorial.hpp +++ b/stan/math/prim/fun/log_rising_factorial.hpp @@ -70,10 +70,13 @@ inline return_type_t log_rising_factorial(const T1& x, const T2& n) { * @return log_rising_factorial function applied to the two inputs. */ template * = nullptr> -inline auto log_rising_factorial(const T1& a, const T2& b) { +inline auto log_rising_factorial(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return log_rising_factorial(c, d); }, - a, b); + [](auto&& c, auto&& d) { + return log_rising_factorial(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/log_softmax.hpp b/stan/math/prim/fun/log_softmax.hpp index 62d753293f6..1b81f40a62c 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -41,14 +41,15 @@ namespace math { */ template * = nullptr, require_container_t* = nullptr> -inline auto log_softmax(const Container& x) { +inline auto log_softmax(Container&& x) { check_nonzero_size("log_softmax", "v", x); return make_holder( - [](const auto& a) { + [](auto&& a) { return apply_vector_unary>::apply( - a, [](const auto& v) { return v.array() - log_sum_exp(v); }); + std::forward(a), + [](const auto& v) { return v.array() - log_sum_exp(v); }); }, - to_ref(x)); + to_ref(std::forward(x))); } } // namespace math diff --git a/stan/math/prim/fun/log_sum_exp.hpp b/stan/math/prim/fun/log_sum_exp.hpp index 128b9cd8189..8f2244517e7 100644 --- a/stan/math/prim/fun/log_sum_exp.hpp +++ b/stan/math/prim/fun/log_sum_exp.hpp @@ -79,8 +79,8 @@ inline return_type_t log_sum_exp(const T2& a, const T1& b) { * @return The log of the sum of the exponentiated vector values. */ template * = nullptr> -inline auto log_sum_exp(const T& x) { - return apply_vector_unary::reduce(x, [&](const auto& v) { +inline auto log_sum_exp(T&& x) { + return apply_vector_unary::reduce(std::forward(x), [](const auto& v) { if (v.size() == 0) { return NEGATIVE_INFTY; } @@ -104,9 +104,13 @@ inline auto log_sum_exp(const T& x) { * @return log_sum_exp function applied to the two inputs. */ template * = nullptr> -inline auto log_sum_exp(const T1& a, const T2& b) { +inline auto log_sum_exp(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return log_sum_exp(c, d); }, a, b); + [](auto&& c, auto&& d) { + return log_sum_exp(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/logit.hpp b/stan/math/prim/fun/logit.hpp index 3f6f7ce7a8c..b05ccf6288d 100644 --- a/stan/math/prim/fun/logit.hpp +++ b/stan/math/prim/fun/logit.hpp @@ -71,8 +71,8 @@ struct logit_fun { * @return log odds of the argument */ template - static inline auto fun(const T& x) { - return logit(x); + static inline auto fun(T&& x) { + return logit(std::forward(x)); } }; @@ -87,8 +87,9 @@ struct logit_fun { * @return elementwise logit of container elements */ template * = nullptr> -inline auto logit(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto logit(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -104,14 +105,14 @@ inline auto logit(const Container& x) { */ template * = nullptr> -inline auto logit(const Container& x) { +inline auto logit(Container&& x) { return make_holder( - [](const auto& v_ref) { + [](auto&& v_ref) { return apply_vector_unary>::apply( - v_ref, + std::forward(v_ref), [](const auto& v) { return (v.array() / (1 - v.array())).log(); }); }, - to_ref(x)); + to_ref(std::forward(x))); } } // namespace math diff --git a/stan/math/prim/fun/max.hpp b/stan/math/prim/fun/max.hpp index 7ca81daa8f6..0d14411fd80 100644 --- a/stan/math/prim/fun/max.hpp +++ b/stan/math/prim/fun/max.hpp @@ -39,14 +39,14 @@ auto max(T1 x, T2 y) { * scalar type in the container is integer */ template * = nullptr> -inline value_type_t max(const T& m) { +inline value_type_t max(T&& m) { if (std::is_integral>::value) { check_nonzero_size("max", "int vector", m); } else if (m.size() == 0) { return NEGATIVE_INFTY; } return apply_vector_unary::reduce( - m, [](const auto& x) { return x.maxCoeff(); }); + std::forward(m), [](const auto& x) { return x.maxCoeff(); }); } } // namespace math diff --git a/stan/math/prim/fun/mean.hpp b/stan/math/prim/fun/mean.hpp index aff32358d41..4dbe3d50cac 100644 --- a/stan/math/prim/fun/mean.hpp +++ b/stan/math/prim/fun/mean.hpp @@ -19,9 +19,9 @@ namespace math { * @return Sample mean of container coefficients. */ template * = nullptr> -inline return_type_t mean(const T& m) { +inline return_type_t mean(T&& m) { check_nonzero_size("mean", "m", m); - return apply_vector_unary::reduce(m, + return apply_vector_unary::reduce(std::forward(m), [](const auto& a) { return a.mean(); }); } diff --git a/stan/math/prim/fun/min.hpp b/stan/math/prim/fun/min.hpp index 9d84a38ac93..a96a296bf59 100644 --- a/stan/math/prim/fun/min.hpp +++ b/stan/math/prim/fun/min.hpp @@ -38,14 +38,14 @@ auto min(T1 x, T2 y) { * scalar type in the container is integer */ template * = nullptr> -inline value_type_t min(const T& m) { +inline value_type_t min(T&& m) { if (std::is_integral>::value) { check_nonzero_size("min", "int vector", m); } else if (m.size() == 0) { return INFTY; } return apply_vector_unary::reduce( - m, [](const auto& x) { return x.minCoeff(); }); + std::forward(m), [](const auto& x) { return x.minCoeff(); }); } } // namespace math diff --git a/stan/math/prim/fun/minus.hpp b/stan/math/prim/fun/minus.hpp index b2830183ad3..a91acf53852 100644 --- a/stan/math/prim/fun/minus.hpp +++ b/stan/math/prim/fun/minus.hpp @@ -15,8 +15,8 @@ namespace math { * @return Negation of subtrahend. */ template * = nullptr> -inline auto minus(const T& x) { - return -x; +inline auto minus(T&& x) { + return make_holder([](auto&& x_) { return -x_; }, std::forward(x)); } /** @@ -26,10 +26,10 @@ inline auto minus(const T& x) { * @param x Container. * @return Container where each element is negated. */ -template -inline auto minus(const std::vector& x) { - return apply_vector_unary>::apply( - x, [](const auto& v) { return -v; }); +template * = nullptr> +inline auto minus(T&& x) { + return apply_vector_unary::apply(std::forward(x), + [](const auto& v) { return -v; }); } } // namespace math diff --git a/stan/math/prim/fun/modified_bessel_first_kind.hpp b/stan/math/prim/fun/modified_bessel_first_kind.hpp index 25a6f214726..448787662a7 100644 --- a/stan/math/prim/fun/modified_bessel_first_kind.hpp +++ b/stan/math/prim/fun/modified_bessel_first_kind.hpp @@ -63,12 +63,13 @@ inline double modified_bessel_first_kind(int v, int z) { * @return modified_bessel_first_kind function applied to the two inputs. */ template * = nullptr> -inline auto modified_bessel_first_kind(const T1& a, const T2& b) { +inline auto modified_bessel_first_kind(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { - return modified_bessel_first_kind(c, d); + [](auto&& c, auto&& d) { + return modified_bessel_first_kind(std::forward(c), + std::forward(d)); }, - a, b); + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/modified_bessel_second_kind.hpp b/stan/math/prim/fun/modified_bessel_second_kind.hpp index cfb00030ae8..1f4bf7edfe0 100644 --- a/stan/math/prim/fun/modified_bessel_second_kind.hpp +++ b/stan/math/prim/fun/modified_bessel_second_kind.hpp @@ -55,12 +55,13 @@ inline T2 modified_bessel_second_kind(int v, const T2 z) { * @return modified_bessel_second_kind function applied to the two inputs. */ template * = nullptr> -inline auto modified_bessel_second_kind(const T1& a, const T2& b) { +inline auto modified_bessel_second_kind(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { - return modified_bessel_second_kind(c, d); + [](auto&& c, auto&& d) { + return modified_bessel_second_kind(std::forward(c), + std::forward(d)); }, - a, b); + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/multiply_log.hpp b/stan/math/prim/fun/multiply_log.hpp index 6dcd8909999..fb5010d9e27 100644 --- a/stan/math/prim/fun/multiply_log.hpp +++ b/stan/math/prim/fun/multiply_log.hpp @@ -67,9 +67,13 @@ inline return_type_t multiply_log(const T_a a, const T_b b) { */ template * = nullptr, require_all_not_var_matrix_t* = nullptr> -inline auto multiply_log(const T1& a, const T2& b) { +inline auto multiply_log(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return multiply_log(c, d); }, a, b); + [](auto&& c, auto&& d) { + return multiply_log(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/norm1.hpp b/stan/math/prim/fun/norm1.hpp index c842ff27917..d3781e9f5e0 100644 --- a/stan/math/prim/fun/norm1.hpp +++ b/stan/math/prim/fun/norm1.hpp @@ -12,14 +12,16 @@ namespace math { * Returns L1 norm of a vector. For vectors that equals the * sum of magnitudes of its individual elements. * - * @tparam T type of the vector (must be derived from \c Eigen::MatrixBase) - * @param v Vector. + * @tparam Container type of the vector (must be derived from \c + * Eigen::MatrixBase) + * @param x Vector. * @return L1 norm of v. */ -template * = nullptr> -inline double norm1(const T& v) { - ref_type_t v_ref = v; - return v_ref.template lpNorm<1>(); +template * = nullptr> +inline double norm1(Container&& x) { + ref_type_t x_ref = x; + return x_ref.template lpNorm<1>(); } /** @@ -27,13 +29,14 @@ inline double norm1(const T& v) { * sum of magnitudes of its individual elements. * * @tparam Container type of the vector (must be derived from \c std::Vector) - * @param v Vector. + * @param x Vector. * @return L1 norm of v. */ template * = nullptr> -inline auto norm1(const Container& x) { +inline auto norm1(Container&& x) { return apply_vector_unary::reduce( - x, [](const auto& v) { return norm1(v); }); + std::forward(x), + [](auto&& x_) { return norm1(std::forward(x_)); }); } } // namespace math diff --git a/stan/math/prim/fun/norm2.hpp b/stan/math/prim/fun/norm2.hpp index 07040003943..a5cb326a370 100644 --- a/stan/math/prim/fun/norm2.hpp +++ b/stan/math/prim/fun/norm2.hpp @@ -12,14 +12,16 @@ namespace math { * Returns L2 norm of a vector. For vectors that equals the square-root of the * sum of squares of the elements. * - * @tparam T type of the vector (must be derived from \c Eigen::MatrixBase) - * @param v Vector. - * @return L2 norm of v. + * @tparam Container type of the vector (must be derived from \c + * Eigen::MatrixBase) + * @param x Vector. + * @return L2 norm of x. */ -template * = nullptr> -inline double norm2(const T& v) { - ref_type_t v_ref = v; - return v_ref.template lpNorm<2>(); +template * = nullptr> +inline double norm2(Container&& x) { + ref_type_t x_ref = x; + return x_ref.template lpNorm<2>(); } /** @@ -27,13 +29,14 @@ inline double norm2(const T& v) { * sum of squares of the elements. * * @tparam Container type of the vector (must be derived from \c std::vector) - * @param v Vector. - * @return L2 norm of v. + * @param x Vector. + * @return L2 norm of x. */ template * = nullptr> -inline auto norm2(const Container& x) { +inline auto norm2(Container&& x) { return apply_vector_unary::reduce( - x, [](const auto& v) { return norm2(v); }); + std::forward(x), + [](auto&& x_) { return norm2(std::forward(x_)); }); } } // namespace math diff --git a/stan/math/prim/fun/owens_t.hpp b/stan/math/prim/fun/owens_t.hpp index 88f4302e8aa..8ddd9fabf56 100644 --- a/stan/math/prim/fun/owens_t.hpp +++ b/stan/math/prim/fun/owens_t.hpp @@ -74,9 +74,13 @@ inline double owens_t(double h, double a) { */ template * = nullptr, require_all_not_var_and_matrix_types* = nullptr> -inline auto owens_t(const T1& a, const T2& b) { +inline auto owens_t(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return owens_t(c, d); }, a, b); + [](auto&& c, auto&& d) { + return owens_t(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/plus.hpp b/stan/math/prim/fun/plus.hpp index 4a5c6f2177f..d1078c23894 100644 --- a/stan/math/prim/fun/plus.hpp +++ b/stan/math/prim/fun/plus.hpp @@ -14,7 +14,7 @@ namespace math { * @return result of unary plus of the input. */ template -inline T plus(T&& x) { +inline auto plus(T&& x) { return std::forward(x); } diff --git a/stan/math/prim/fun/pow.hpp b/stan/math/prim/fun/pow.hpp index b93957891c6..90db4a4fc85 100644 --- a/stan/math/prim/fun/pow.hpp +++ b/stan/math/prim/fun/pow.hpp @@ -108,10 +108,14 @@ inline auto pow(const T1& a, const T2& b) { template * = nullptr, require_all_not_matrix_st* = nullptr, require_all_arithmetic_t, base_type_t>* = nullptr> -inline auto pow(const T1& a, const T2& b) { +inline auto pow(T1&& a, T2&& b) { return apply_scalar_binary( // Qualified pow since only Arithmetic types are accepted here - [](const auto& c, const auto& d) { return stan::math::pow(c, d); }, a, b); + [](auto&& c, auto&& d) { + return stan::math::pow(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math } // namespace stan diff --git a/stan/math/prim/fun/rank.hpp b/stan/math/prim/fun/rank.hpp index 9378a5c120b..29285b4cf5d 100644 --- a/stan/math/prim/fun/rank.hpp +++ b/stan/math/prim/fun/rank.hpp @@ -17,14 +17,15 @@ namespace math { * @throw std::out_of_range if s is out of range. */ template * = nullptr> -inline int rank(const C& v, int s) { +inline int rank(C&& v, int s) { check_range("rank", "v", v.size(), s); --s; // adjust for indexing by one - return apply_vector_unary::reduce(v, [s](const auto& vec) { - const auto& vec_ref = to_ref(vec); + return apply_vector_unary::reduce( + std::forward(v), [s](const auto& vec) { + const auto& vec_ref = to_ref(vec); - return (vec_ref.array() < vec_ref.coeff(s)).template cast().sum(); - }); + return (vec_ref.array() < vec_ref.coeff(s)).template cast().sum(); + }); } } // namespace math diff --git a/stan/math/prim/fun/rising_factorial.hpp b/stan/math/prim/fun/rising_factorial.hpp index 5a93b9f079f..c3288b9e7b0 100644 --- a/stan/math/prim/fun/rising_factorial.hpp +++ b/stan/math/prim/fun/rising_factorial.hpp @@ -78,10 +78,13 @@ inline return_type_t rising_factorial(const T& x, int n) { * @return rising_factorial function applied to the two inputs. */ template * = nullptr> -inline auto rising_factorial(const T1& a, const T2& b) { +inline auto rising_factorial(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return rising_factorial(c, d); }, a, - b); + [](auto&& c, auto&& d) { + return rising_factorial(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/prim/fun/round.hpp b/stan/math/prim/fun/round.hpp index 5ed3649bc47..0a4d2090441 100644 --- a/stan/math/prim/fun/round.hpp +++ b/stan/math/prim/fun/round.hpp @@ -10,6 +10,11 @@ namespace stan { namespace math { +template * = nullptr> +inline auto round(T&& x) { + return std::round(x); +} + /** * Structure to wrap `round()` so it can be vectorized. * @@ -19,9 +24,12 @@ namespace math { */ struct round_fun { template - static inline auto fun(const T& x) { - using std::round; - return round(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::round(x); + } else { + return round(std::forward(x)); + } } }; @@ -35,9 +43,11 @@ struct round_fun { template * = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< - Container>* = nullptr> -inline auto round(const Container& x) { - return apply_scalar_unary::apply(x); + Container>* = nullptr, + require_container_t* = nullptr> +inline auto round(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -50,9 +60,10 @@ inline auto round(const Container& x) { */ template * = nullptr> -inline auto round(const Container& x) { +inline auto round(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().round(); }); + std::forward(x), + [](const auto& v) { return v.array().round(); }); } } // namespace math diff --git a/stan/math/prim/fun/sd.hpp b/stan/math/prim/fun/sd.hpp index 39223a6135b..ab053b3a2c2 100644 --- a/stan/math/prim/fun/sd.hpp +++ b/stan/math/prim/fun/sd.hpp @@ -23,10 +23,10 @@ namespace math { */ template * = nullptr, require_not_st_var* = nullptr> -inline auto sd(const T& m) { +inline auto sd(T&& m) { using std::sqrt; - return apply_vector_unary::reduce(m, [](const auto& x) { + return apply_vector_unary::reduce(std::forward(m), [](const auto& x) { check_nonzero_size("sd", "x", x); if (x.size() == 1) { diff --git a/stan/math/prim/fun/select.hpp b/stan/math/prim/fun/select.hpp index def8bd3d67c..a3ee9c39bc2 100644 --- a/stan/math/prim/fun/select.hpp +++ b/stan/math/prim/fun/select.hpp @@ -80,8 +80,7 @@ template >, require_container_t* = nullptr, require_stan_scalar_t* = nullptr> -inline ReturnT select(const bool c, const T_true& y_true, - const T_false& y_false) { +inline ReturnT select(const bool c, T_true&& y_true, const T_false& y_false) { if (c) { return y_true; } else { @@ -89,7 +88,7 @@ inline ReturnT select(const bool c, const T_true& y_true, [](const auto& y_true_inner, const auto& y_false_inner) { return y_false_inner; }, - y_true, y_false); + std::forward(y_true), y_false); } } @@ -115,14 +114,13 @@ template >, require_stan_scalar_t* = nullptr, require_container_t* = nullptr> -inline ReturnT select(const bool c, const T_true y_true, - const T_false y_false) { +inline ReturnT select(const bool c, const T_true y_true, T_false&& y_false) { if (c) { return apply_scalar_binary( [](const auto& y_true_inner, const auto& y_false_inner) { return y_true_inner; }, - y_true, y_false); + y_true, std::forward(y_false)); } else { return y_false; } diff --git a/stan/math/prim/fun/sign.hpp b/stan/math/prim/fun/sign.hpp index 0651030f0eb..3d525c1afef 100644 --- a/stan/math/prim/fun/sign.hpp +++ b/stan/math/prim/fun/sign.hpp @@ -39,8 +39,8 @@ struct sign_fun { * @return Elementwise sign of members of container. */ template * = nullptr> -inline auto sign(const T& x) { - return apply_scalar_unary::apply(x); +inline auto sign(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/sin.hpp b/stan/math/prim/fun/sin.hpp index a0145dd4c6b..d62dd879d7a 100644 --- a/stan/math/prim/fun/sin.hpp +++ b/stan/math/prim/fun/sin.hpp @@ -21,7 +21,7 @@ namespace math { * @return sine of the argument */ template * = nullptr> -inline auto sin(const T x) { +inline auto sin(T&& x) { return std::sin(x); } @@ -33,7 +33,7 @@ inline auto sin(const T x) { * @return sine of the argument */ template * = nullptr> -inline auto sin(const T x) { +inline auto sin(T&& x) { return std::sin(x); } @@ -46,8 +46,12 @@ inline auto sin(const T x) { */ struct sin_fun { template - static inline auto fun(const T& x) { - return sin(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::sin(x); + } else { + return sin(std::forward(x)); + } } }; @@ -59,8 +63,8 @@ struct sin_fun { * @return Sine of each value in x. */ template * = nullptr> -inline auto sin(const T& x) { - return apply_scalar_unary::apply(x); +inline auto sin(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } /** @@ -73,9 +77,10 @@ inline auto sin(const T& x) { */ template * = nullptr> -inline auto sin(const Container& x) { +inline auto sin(Container&& x) { return apply_vector_unary::apply( - x, [&](const auto& v) { return v.array().sin(); }); + std::forward(x), + [&](const auto& v) { return v.array().sin(); }); } namespace internal { diff --git a/stan/math/prim/fun/sinh.hpp b/stan/math/prim/fun/sinh.hpp index e3e55fa7477..84448e01c75 100644 --- a/stan/math/prim/fun/sinh.hpp +++ b/stan/math/prim/fun/sinh.hpp @@ -19,7 +19,7 @@ namespace math { * @return hyperbolic sine of the argument */ template * = nullptr> -inline auto sinh(const T x) { +inline auto sinh(T&& x) { return std::sinh(x); } @@ -31,7 +31,7 @@ inline auto sinh(const T x) { * @return hyperbolic sine of the argument */ template * = nullptr> -inline auto sinh(const T x) { +inline auto sinh(T&& x) { return std::sinh(x); } @@ -44,8 +44,12 @@ inline auto sinh(const T x) { */ struct sinh_fun { template - static inline auto fun(const T& x) { - return sinh(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::sinh(x); + } else { + return sinh(std::forward(x)); + } } }; @@ -57,8 +61,9 @@ struct sinh_fun { * @return Hyperbolic sine of each variable in x. */ template * = nullptr> -inline auto sinh(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto sinh(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -71,9 +76,9 @@ inline auto sinh(const Container& x) { */ template * = nullptr> -inline auto sinh(const Container& x) { +inline auto sinh(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().sinh(); }); + std::forward(x), [](auto&& v) { return v.array().sinh(); }); } namespace internal { diff --git a/stan/math/prim/fun/sqrt.hpp b/stan/math/prim/fun/sqrt.hpp index 3e1620d2a61..4523c4d2f05 100644 --- a/stan/math/prim/fun/sqrt.hpp +++ b/stan/math/prim/fun/sqrt.hpp @@ -19,7 +19,7 @@ namespace math { * @return square root of the argument */ template * = nullptr> -inline auto sqrt(const T x) { +inline auto sqrt(T&& x) { return std::sqrt(x); } @@ -31,7 +31,7 @@ inline auto sqrt(const T x) { * @return square root of the argument */ template * = nullptr> -inline auto sqrt(const T x) { +inline auto sqrt(T&& x) { return std::sqrt(x); } @@ -44,8 +44,12 @@ inline auto sqrt(const T x) { */ struct sqrt_fun { template - static inline auto fun(const T& x) { - return sqrt(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::sqrt(x); + } else { + return sqrt(std::forward(x)); + } } }; @@ -57,8 +61,9 @@ struct sqrt_fun { * @return Square root of each value in x. */ template * = nullptr> -inline auto sqrt(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto sqrt(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -72,9 +77,9 @@ inline auto sqrt(const Container& x) { template * = nullptr, require_not_var_matrix_t* = nullptr> -inline auto sqrt(const Container& x) { +inline auto sqrt(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().sqrt(); }); + std::forward(x), [](auto&& v) { return v.array().sqrt(); }); } namespace internal { diff --git a/stan/math/prim/fun/square.hpp b/stan/math/prim/fun/square.hpp index cb14bd77c8b..0ed671bb96d 100644 --- a/stan/math/prim/fun/square.hpp +++ b/stan/math/prim/fun/square.hpp @@ -37,8 +37,8 @@ inline double square(const T x) { */ struct square_fun { template - static inline auto fun(const T& x) { - return square(x); + static inline auto fun(T&& x) { + return square(std::forward(x)); } }; @@ -50,8 +50,9 @@ struct square_fun { * @return Each value in x squared. */ template * = nullptr> -inline auto square(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto square(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -64,9 +65,9 @@ inline auto square(const Container& x) { */ template * = nullptr> -inline auto square(const Container& x) { +inline auto square(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().square(); }); + std::forward(x), [](auto&& v) { return v.array().square(); }); } } // namespace math diff --git a/stan/math/prim/fun/step.hpp b/stan/math/prim/fun/step.hpp index c75d164fd2b..d2663f0b2ee 100644 --- a/stan/math/prim/fun/step.hpp +++ b/stan/math/prim/fun/step.hpp @@ -58,8 +58,8 @@ struct step_fun { * @return Elementwise step of members of container. */ template * = nullptr> -inline auto step(const T& x) { - return apply_scalar_unary::apply(x); +inline auto step(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/sum.hpp b/stan/math/prim/fun/sum.hpp index 0440997fda0..fbf99e973d4 100644 --- a/stan/math/prim/fun/sum.hpp +++ b/stan/math/prim/fun/sum.hpp @@ -18,7 +18,7 @@ namespace math { * @return Same value (the sum of one value). */ template * = nullptr> -inline T sum(T&& m) { +inline auto sum(T&& m) { return std::forward(m); } diff --git a/stan/math/prim/fun/tan.hpp b/stan/math/prim/fun/tan.hpp index 373672eb0c8..dc9aa4b5bb6 100644 --- a/stan/math/prim/fun/tan.hpp +++ b/stan/math/prim/fun/tan.hpp @@ -21,7 +21,7 @@ namespace math { * @return tangent of the argument */ template * = nullptr> -inline auto tan(const T x) { +inline auto tan(T&& x) { return std::tan(x); } @@ -33,7 +33,7 @@ inline auto tan(const T x) { * @return tangent of the argument */ template * = nullptr> -inline auto tan(const T x) { +inline auto tan(T&& x) { return std::tan(x); } @@ -46,8 +46,12 @@ inline auto tan(const T x) { */ struct tan_fun { template - static inline auto fun(const T& x) { - return tan(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::tan(x); + } else { + return tan(std::forward(x)); + } } }; @@ -59,8 +63,9 @@ struct tan_fun { * @return Tangent of each value in x. */ template * = nullptr> -inline auto tan(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto tan(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -73,9 +78,9 @@ inline auto tan(const Container& x) { */ template * = nullptr> -inline auto tan(const Container& x) { +inline auto tan(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().tan(); }); + std::forward(x), [](auto&& v) { return v.array().tan(); }); } namespace internal { diff --git a/stan/math/prim/fun/tanh.hpp b/stan/math/prim/fun/tanh.hpp index 1ae3faff087..34abd6032b9 100644 --- a/stan/math/prim/fun/tanh.hpp +++ b/stan/math/prim/fun/tanh.hpp @@ -21,7 +21,7 @@ namespace math { * @return hyperbolic tangent of the argument */ template * = nullptr> -inline auto tanh(const T x) { +inline auto tanh(T&& x) { return std::tanh(x); } @@ -33,7 +33,7 @@ inline auto tanh(const T x) { * @return hyperbolic tangent of the argument */ template * = nullptr> -inline auto tanh(const T x) { +inline auto tanh(T&& x) { return std::tanh(x); } @@ -46,8 +46,12 @@ inline auto tanh(const T x) { */ struct tanh_fun { template - static inline auto fun(const T& x) { - return tanh(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::tanh(x); + } else { + return tanh(std::forward(x)); + } } }; @@ -59,8 +63,9 @@ struct tanh_fun { * @return Hyperbolic tangent of each value in x. */ template * = nullptr> -inline auto tanh(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto tanh(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -73,9 +78,9 @@ inline auto tanh(const Container& x) { */ template * = nullptr> -inline auto tanh(const Container& x) { +inline auto tanh(Container&& x) { return apply_vector_unary::apply( - x, [](const auto& v) { return v.array().tanh(); }); + std::forward(x), [](auto&& v) { return v.array().tanh(); }); } namespace internal { diff --git a/stan/math/prim/fun/tgamma.hpp b/stan/math/prim/fun/tgamma.hpp index c038b699ab7..8b6e0899913 100644 --- a/stan/math/prim/fun/tgamma.hpp +++ b/stan/math/prim/fun/tgamma.hpp @@ -33,8 +33,8 @@ inline double tgamma(double x) { */ struct tgamma_fun { template - static inline auto fun(const T& x) { - return tgamma(x); + static inline auto fun(T&& x) { + return tgamma(std::forward(x)); } }; @@ -49,9 +49,9 @@ struct tgamma_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto tgamma(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> +inline auto tgamma(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/to_complex.hpp b/stan/math/prim/fun/to_complex.hpp index ea0122595c1..f5777bfc17c 100644 --- a/stan/math/prim/fun/to_complex.hpp +++ b/stan/math/prim/fun/to_complex.hpp @@ -37,10 +37,13 @@ constexpr inline std::complex> to_complex( */ template * = nullptr, require_all_st_stan_scalar* = nullptr> -inline auto to_complex(const T1& re, const T2& im) { +inline auto to_complex(T1&& re, T2&& im) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return stan::math::to_complex(c, d); }, - re, im); + [](auto&& c, auto&& d) { + return stan::math::to_complex(std::forward(c), + std::forward(d)); + }, + std::forward(re), std::forward(im)); } } // namespace math diff --git a/stan/math/prim/fun/to_int.hpp b/stan/math/prim/fun/to_int.hpp index ea286f55925..d8f84c76e6c 100644 --- a/stan/math/prim/fun/to_int.hpp +++ b/stan/math/prim/fun/to_int.hpp @@ -56,8 +56,8 @@ inline int to_int(T x) { */ struct to_int_fun { template - static inline auto fun(const T& x) { - return to_int(x); + static inline auto fun(T&& x) { + return to_int(std::forward(x)); } }; @@ -71,8 +71,9 @@ struct to_int_fun { */ template * = nullptr> -inline auto to_int(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto to_int(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/trigamma.hpp b/stan/math/prim/fun/trigamma.hpp index 9a30daab99b..45b2d534d3b 100644 --- a/stan/math/prim/fun/trigamma.hpp +++ b/stan/math/prim/fun/trigamma.hpp @@ -138,8 +138,8 @@ struct trigamma_fun { * @return trigamma applied to argument. */ template - static inline auto fun(const T& x) { - return trigamma(x); + static inline auto fun(T&& x) { + return trigamma(std::forward(x)); } }; @@ -154,9 +154,10 @@ struct trigamma_fun { * @return elementwise trigamma of container elements */ template * = nullptr> -inline auto trigamma(const T& x) { - return apply_scalar_unary::apply(x); + require_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto trigamma(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/trunc.hpp b/stan/math/prim/fun/trunc.hpp index 4a5b1c1d79b..15eea016251 100644 --- a/stan/math/prim/fun/trunc.hpp +++ b/stan/math/prim/fun/trunc.hpp @@ -8,6 +8,10 @@ namespace stan { namespace math { +template * = nullptr> +inline auto trunc(T&& x) { + return std::trunc(x); +} /** * Structure to wrap `trunc()` so it can be vectorized. */ @@ -21,9 +25,12 @@ struct trunc_fun { * @return truncation of the argument */ template - static inline auto fun(const T& x) { - using std::trunc; - return trunc(x); + static inline auto fun(T&& x) { + if constexpr (std::is_arithmetic_v>) { + return std::trunc(x); + } else { + return trunc(std::forward(x)); + } } }; @@ -37,10 +44,12 @@ struct trunc_fun { * @param x container * @return elementwise trunc of container elements */ -template * = nullptr> -inline auto trunc(const T& x) { - return apply_scalar_unary::apply(x); +template < + typename T, + require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, + require_container_t* = nullptr> +inline auto trunc(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/functor/apply_scalar_binary.hpp b/stan/math/prim/functor/apply_scalar_binary.hpp index a896df33914..56ee43c0802 100644 --- a/stan/math/prim/functor/apply_scalar_binary.hpp +++ b/stan/math/prim/functor/apply_scalar_binary.hpp @@ -34,8 +34,8 @@ namespace math { */ template * = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { - return f(x, y); +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { + return std::forward(f)(std::forward(x), std::forward(y)); } /** @@ -57,7 +57,9 @@ inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { check_matching_dims("Binary function", "x", x, "y", y); return make_holder( [](auto&& f_inner, auto&& x_inner, auto&& y_inner) { - return x_inner.binaryExpr(y_inner, f_inner); + return std::forward(x_inner).binaryExpr( + std::forward(y_inner), + std::forward(f_inner)); }, std::forward(f), std::forward(x), std::forward(y)); } @@ -84,7 +86,8 @@ inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { using int_vec_t = promote_scalar_t, plain_type_t>; Eigen::Map y_map(y_inner.data(), y_inner.size()); - return x_inner.binaryExpr(y_map, f_inner); + return std::forward(x_inner).binaryExpr( + y_map, std::forward(f_inner)); }, std::forward(f), std::forward(x), std::forward(y)); } @@ -111,7 +114,8 @@ inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { using int_vec_t = promote_scalar_t, plain_type_t>; Eigen::Map x_map(x_inner.data(), x_inner.size()); - return x_map.binaryExpr(y_inner, f_inner); + return x_map.binaryExpr(std::forward(y_inner), + std::forward(f_inner)); }, std::forward(f), std::forward(x), std::forward(y)); } @@ -132,7 +136,7 @@ template * = nullptr, require_std_vector_vt* = nullptr, require_std_vector_st* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { if (num_elements(x) != num_elements(y)) { std::ostringstream msg; msg << "Inputs to vectorized binary function must match in" @@ -165,7 +169,7 @@ template * = nullptr, require_std_vector_st* = nullptr, require_eigen_matrix_dynamic_vt* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { if (num_elements(x) != num_elements(y)) { std::ostringstream msg; msg << "Inputs to vectorized binary function must match in" @@ -202,8 +206,9 @@ template * = nullptr, inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { return make_holder( [](auto&& f_inner, auto&& x_inner, auto&& y_inner) { - return x_inner.unaryExpr( - [f_inner, y_inner](const auto& v) { return f_inner(v, y_inner); }); + return std::forward(x_inner).unaryExpr( + [f_inner_ = std::forward(f_inner), + y_inner](auto&& v) { return f_inner_(v, y_inner); }); }, std::forward(f), std::forward(x), std::forward(y)); } @@ -228,8 +233,11 @@ template (y_inner).unaryExpr( + [f_inner_ = std::forward(f_inner), + x_inner](auto&& v) { + return f_inner_(x_inner, std::forward(v)); + }); }, std::forward(f), std::forward(x), std::forward(y)); } @@ -253,14 +261,14 @@ inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { */ template * = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { check_matching_sizes("Binary function", "x", x, "y", y); - decltype(auto) x_vec = as_column_vector_or_scalar(x); - decltype(auto) y_vec = as_column_vector_or_scalar(y); + decltype(auto) x_vec = as_column_vector_or_scalar(std::forward(x)); + decltype(auto) y_vec = as_column_vector_or_scalar(std::forward(y)); using T_return = std::decay_t; std::vector result(x.size()); Eigen::Map>(result.data(), result.size()) - = x_vec.binaryExpr(y_vec, f); + = x_vec.binaryExpr(y_vec, std::forward(f)); return result; } @@ -285,12 +293,13 @@ inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { template * = nullptr, require_stan_scalar_t* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { - decltype(auto) x_vec = as_column_vector_or_scalar(x); +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { + decltype(auto) x_vec = as_column_vector_or_scalar(std::forward(x)); using T_return = std::decay_t; std::vector result(x.size()); Eigen::Map>(result.data(), result.size()) - = x_vec.unaryExpr([f, y](const auto& v) { return f(v, y); }); + = x_vec.unaryExpr( + [f_ = std::forward(f), y](auto&& v) { return f_(v, y); }); return result; } @@ -315,12 +324,13 @@ inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { template * = nullptr, require_std_vector_vt* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { decltype(auto) y_vec = as_column_vector_or_scalar(y); using T_return = std::decay_t; std::vector result(y.size()); Eigen::Map>(result.data(), result.size()) - = y_vec.unaryExpr([f, x](const auto& v) { return f(x, v); }); + = y_vec.unaryExpr( + [f_ = std::forward(f), x](auto&& v) { return f_(x, v); }); return result; } @@ -341,7 +351,7 @@ inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { template < typename F, typename T1, typename T2, require_all_std_vector_vt* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { check_matching_sizes("Binary function", "x", x, "y", y); using T_return = plain_type_t; size_t y_size = y.size(); @@ -369,7 +379,7 @@ inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { template * = nullptr, require_stan_scalar_t* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { using T_return = plain_type_t; size_t x_size = x.size(); std::vector result(x_size); @@ -396,7 +406,7 @@ inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { template * = nullptr, require_std_vector_vt* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { using T_return = plain_type_t; size_t y_size = y.size(); std::vector result(y_size); diff --git a/stan/math/prim/functor/apply_scalar_ternary.hpp b/stan/math/prim/functor/apply_scalar_ternary.hpp index 7876c72895d..e50b558d3af 100644 --- a/stan/math/prim/functor/apply_scalar_ternary.hpp +++ b/stan/math/prim/functor/apply_scalar_ternary.hpp @@ -36,9 +36,9 @@ namespace math { */ template * = nullptr> -inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, - const T3& z) { - return f(x, y, z); +inline auto apply_scalar_ternary(F&& f, T1&& x, T2&& y, T3&& z) { + return std::forward(f)(std::forward(x), std::forward(y), + std::forward(z)); } /** @@ -93,8 +93,7 @@ inline auto apply_scalar_ternary(F&& f, T1&& x, T2&& y, T3&& z) { */ template * = nullptr> -inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, - const T3& z) { +inline auto apply_scalar_ternary(F&& f, T1&& x, T2&& y, T3&& z) { check_matching_sizes("Ternary function", "x", x, "y", y); check_matching_sizes("Ternary function", "y", y, "z", z); decltype(auto) x_vec = as_column_vector_or_scalar(x); @@ -103,7 +102,7 @@ inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, using T_return = std::decay_t; std::vector result(x.size()); Eigen::Map>(result.data(), result.size()) - = apply_scalar_ternary(f, x_vec, y_vec, z_vec); + = apply_scalar_ternary(std::forward(f), x_vec, y_vec, z_vec); return result; } @@ -126,8 +125,7 @@ inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, template * = nullptr> -inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, - const T3& z) { +inline auto apply_scalar_ternary(F&& f, T1&& x, T2&& y, T3&& z) { check_matching_sizes("Ternary function", "x", x, "y", y); check_matching_sizes("Ternary function", "y", y, "z", z); using T_return @@ -159,10 +157,13 @@ inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, template * = nullptr, require_stan_scalar_t* = nullptr> -inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, - const T3& z) { +inline auto apply_scalar_ternary(F&& f, T1&& x, T2&& y, T3&& z) { return apply_scalar_binary( - [f, z](const auto& a, const auto& b) { return f(a, b, z); }, x, y); + [f_ = std::forward(f), z](auto&& a, auto&& b) { + return f_(std::forward(a), std::forward(b), + z); + }, + std::forward(x), std::forward(y)); } /** @@ -184,10 +185,13 @@ inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, template * = nullptr, require_stan_scalar_t* = nullptr> -inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, - const T3& z) { +inline auto apply_scalar_ternary(F&& f, T1&& x, T2&& y, T3&& z) { return apply_scalar_binary( - [f, y](const auto& a, const auto& c) { return f(a, y, c); }, x, z); + [f_ = std::forward(f), y](auto&& a, auto&& c) { + return f_(std::forward(a), y, + std::forward(c)); + }, + std::forward(x), std::forward(z)); } /** @@ -209,10 +213,13 @@ inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, template * = nullptr, require_stan_scalar_t* = nullptr> -inline auto apply_scalar_ternary(const F& f, const T1& x, const T2& y, - const T3& z) { +inline auto apply_scalar_ternary(F&& f, T1&& x, T2&& y, T3&& z) { return apply_scalar_binary( - [f, x](const auto& b, const auto& c) { return f(x, b, c); }, y, z); + [f_ = std::forward(f), x](auto&& b, auto&& c) { + return f_(x, std::forward(b), + std::forward(c)); + }, + std::forward(y), std::forward(z)); } } // namespace math diff --git a/stan/math/prim/functor/apply_scalar_unary.hpp b/stan/math/prim/functor/apply_scalar_unary.hpp index 2cbcae179aa..58312c1ac56 100644 --- a/stan/math/prim/functor/apply_scalar_unary.hpp +++ b/stan/math/prim/functor/apply_scalar_unary.hpp @@ -58,10 +58,15 @@ struct apply_scalar_unary> { * @return Componentwise application of the function specified * by F to the specified matrix. */ - static inline auto apply(const std::decay_t& x) { - return x.unaryExpr([](auto&& x) { - return apply_scalar_unary>::apply(x); - }); + template + static inline auto apply(TT&& x) { + return make_holder( + [](auto&& xx) { + return std::forward(xx).unaryExpr([](auto&& xxx) { + return apply_scalar_unary::apply(xxx); + }); + }, + std::forward(x)); } /** @@ -69,7 +74,7 @@ struct apply_scalar_unary> { * expression template of type T. */ using return_t = std::decay_t>::apply(std::declval()))>; + apply_scalar_unary::apply(std::declval()))>; }; /** @@ -95,7 +100,10 @@ struct apply_scalar_unary> { * @param x Argument scalar. * @return Result of applying F to the scalar. */ - static inline auto apply(T x) { return F::fun(x); } + template + static inline auto apply(T2 x) { + return F::fun(x); + } }; /** @@ -115,7 +123,10 @@ struct apply_scalar_unary> { * @param x Argument scalar. * @return Result of applying F to the scalar. */ - static inline auto apply(const std::decay_t& x) { return F::fun(x); } + template + static inline auto apply(T2&& x) { + return F::fun(std::forward(x)); + } /** * The return type */ @@ -142,7 +153,10 @@ struct apply_scalar_unary> { * @param x Argument scalar. * @return Result of applying F to the scalar. */ - static inline auto apply(T x) { return F::fun(x); } + template + static inline auto apply(T2 x) { + return F::fun(x); + } /** * The return type, double. */ @@ -176,10 +190,15 @@ struct apply_scalar_unary> { * @return Elementwise application of F to the elements of the * container. */ - static inline auto apply(const std::decay_t& x) { + template + static inline auto apply(TT&& x) { return_t fx(x.size()); for (size_t i = 0; i < x.size(); ++i) { - fx[i] = apply_scalar_unary>::apply(x[i]); + if constexpr (std::is_rvalue_reference_v) { + fx[i] = apply_scalar_unary>::apply(std::move(x[i])); + } else { + fx[i] = apply_scalar_unary>::apply(x[i]); + } } return fx; } diff --git a/stan/math/prim/functor/apply_vector_unary.hpp b/stan/math/prim/functor/apply_vector_unary.hpp index 5787043a385..61affed66a8 100644 --- a/stan/math/prim/functor/apply_vector_unary.hpp +++ b/stan/math/prim/functor/apply_vector_unary.hpp @@ -42,15 +42,26 @@ struct apply_vector_unary> { */ template >>* = nullptr> - static inline auto apply(const T& x, const F& f) { - return make_holder([](const auto& a) { return a.matrix().derived(); }, - f(x)); + static inline auto apply(T2&& x, F&& f) { + if constexpr (is_eigen_array::value) { + return make_holder( + [](auto&& xx) { return std::forward(xx).matrix(); }, + make_holder(std::forward(f), std::forward(x))); + } else { + return make_holder(std::forward(f), std::forward(x)); + } } template >>* = nullptr> - static inline auto apply(const T& x, const F& f) { - return make_holder([](const auto& a) { return a.array().derived(); }, f(x)); + static inline auto apply(T2&& x, F&& f) { + if constexpr (is_eigen_array::value) { + return make_holder(std::forward(f), std::forward(x)); + } else { + return make_holder( + [](auto&& xx) { return std::forward(xx).array(); }, + make_holder(std::forward(f), std::forward(x))); + } } /** @@ -67,14 +78,14 @@ struct apply_vector_unary> { */ template >>* = nullptr> - static inline auto apply_no_holder(const T& x, const F& f) { - return f(x).matrix().derived(); + static inline auto apply_no_holder(T2& x, F&& f) { + return std::forward(f)(std::forward(x)); } template >>* = nullptr> - static inline auto apply_no_holder(const T& x, const F& f) { - return f(x).array().derived(); + static inline auto apply_no_holder(T2&& x, F&& f) { + return std::forward(f)(std::forward(x)); } /** @@ -88,9 +99,9 @@ struct apply_vector_unary> { * @param f functor to apply to Eigen input. * @return scalar result of applying functor to input. */ - template - static inline auto reduce(const T& x, const F& f) { - return f(x); + template + static inline auto reduce(T2&& x, F&& f) { + return make_holder(std::forward(f), std::forward(x)); } }; @@ -118,12 +129,14 @@ struct apply_vector_unary> { * @param f functor to apply to vector input. * @return std::vector with result of applying functor to input. */ - template - static inline auto apply(const T& x, const F& f) { - using T_return = value_type_t; + template + static inline auto apply(T2&& x, F&& f) { + using T_return = value_type_t(x))))>; std::vector result(x.size()); Eigen::Map>(result.data(), result.size()) - = f(as_column_vector_or_scalar(x)).matrix(); + = std::forward(f)(as_column_vector_or_scalar(std::forward(x))) + .matrix(); return result; } @@ -138,9 +151,9 @@ struct apply_vector_unary> { * @return std::vector of containers with result of applying functor to * input. */ - template - static inline auto apply_no_holder(const T& x, const F& f) { - return apply(x, f); + template + static inline auto apply_no_holder(T2&& x, F&& f) { + return apply(std::forward(x), std::forward(f)); } /** @@ -153,9 +166,10 @@ struct apply_vector_unary> { * @param f functor to apply to std::vector input. * @return scalar result of applying functor to input vector. */ - template - static inline auto reduce(const T& x, const F& f) { - return apply_vector_unary::reduce(as_column_vector_or_scalar(x), f); + template + static inline auto reduce(T2&& x, F&& f) { + return apply_vector_unary::reduce( + as_column_vector_or_scalar(std::forward(x)), std::forward(f)); } }; @@ -191,7 +205,7 @@ struct apply_vector_unary< = plain_type_t::apply(x[0], f))>; std::vector result(x.size()); std::transform(x.begin(), x.end(), result.begin(), [&f](auto&& xx) { - return apply_vector_unary::apply_no_holder(xx, f); + return apply_vector_unary::apply(xx, f); }); return result; } diff --git a/stan/math/prim/meta/holder.hpp b/stan/math/prim/meta/holder.hpp index a9b3e4afbce..f4a1db6bd55 100644 --- a/stan/math/prim/meta/holder.hpp +++ b/stan/math/prim/meta/holder.hpp @@ -114,8 +114,29 @@ struct is_holder : internal::is_holder> {}; template inline constexpr bool is_holder_v = is_holder::value; +template +using require_holder_t = require_t>; + namespace math { +template < + typename F, typename... Args, + require_not_plain_type_t>* = nullptr> +inline auto make_holder(F&& func, Args&&... args); + +/** + * Calls given function with given arguments. No `holder` is necessary if the + * function is not returning Eigen expression. + * + * @tparam F type of the functor + * @tparam Args types of the arguments + * @param func the functor + * @param args arguments for the functor + * @return `holder` referencing expression constructed by given functor + */ +template >* = nullptr> +inline auto make_holder(F&& func, Args&&... args); /** * A no-op Eigen operation. This object also owns pointers to dynamically * allocated objects used in its argument expression. When this object is @@ -131,9 +152,9 @@ class Holder Nested; typename Eigen::internal::ref_selector::non_const_type m_arg; std::tuple...> m_unique_ptrs; - explicit Holder(ArgType&& arg, Ptrs*... pointers) - : m_arg(arg), m_unique_ptrs(std::unique_ptr(pointers)...) {} + : m_arg(std::forward(arg)), + m_unique_ptrs(std::unique_ptr(pointers)...) {} // we need to explicitely default copy and move constructors as we are // defining copy and move assignment operators @@ -171,6 +192,52 @@ class Holder } }; +template * = nullptr> +inline auto operator-(T&& h) { + return make_holder([](auto&& arg) { return -arg; }, std::forward(h).m_arg); +} +template * = nullptr> +inline auto operator+(T&& h) { + return make_holder([](auto&& arg) { return arg; }, std::forward(h).m_arg); +} + +template * = nullptr, + require_holder_t* = nullptr> +inline auto operator-(T&& h, Other&& other) { + return make_holder( + [](auto&& arg, auto&& other_) { + return arg - std::forward(other_); + }, + std::forward(h).m_arg, std::forward(other)); +} +template * = nullptr, + require_holder_t* = nullptr> +inline auto operator+(T&& h, Other&& other) { + return make_holder( + [](auto&& arg, auto&& other_) { + return arg + std::forward(other_); + }, + std::forward(h).m_arg, std::forward(other)); +} +template * = nullptr, + require_holder_t* = nullptr> +inline auto operator*(T&& h, Other&& other) { + return make_holder( + [](auto&& arg, auto&& other_) { + return arg * std::forward(other_); + }, + std::forward(h).m_arg, std::forward(other)); +} +template * = nullptr, + require_holder_t* = nullptr> +inline auto operator/(T&& h, Other&& other) { + return make_holder( + [](auto&& arg, auto&& other_) { + return arg / std::forward(other_); + }, + std::forward(h).m_arg, std::forward(other)); +} + } // namespace math } // namespace stan @@ -195,6 +262,8 @@ struct evaluator> evaluator m_argImpl; explicit evaluator(const XprType& xpr) : m_argImpl(xpr.m_arg) {} + explicit evaluator(XprType&& xpr) + : m_argImpl(std::forward(xpr).m_arg) {} // all these functions just call the same on the argument EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { @@ -362,9 +431,8 @@ inline auto make_holder_impl(F&& func, std::index_sequence, * @param args arguments for the functor * @return `holder` referencing expression constructed by given functor */ -template < - typename F, typename... Args, - require_not_plain_type_t>* = nullptr> +template >*> inline auto make_holder(F&& func, Args&&... args) { return internal::make_holder_impl(std::forward(func), std::make_index_sequence(), @@ -382,7 +450,7 @@ inline auto make_holder(F&& func, Args&&... args) { * @return `holder` referencing expression constructed by given functor */ template >* = nullptr> + require_plain_type_t>*> inline auto make_holder(F&& func, Args&&... args) { return std::forward(func)(std::forward(args)...); } diff --git a/stan/math/prim/prob/std_normal_log_qf.hpp b/stan/math/prim/prob/std_normal_log_qf.hpp index 895b4997a0a..c21b7279890 100644 --- a/stan/math/prim/prob/std_normal_log_qf.hpp +++ b/stan/math/prim/prob/std_normal_log_qf.hpp @@ -132,8 +132,8 @@ inline double std_normal_log_qf(double log_p) { */ struct std_normal_log_qf_fun { template - static inline auto fun(const T& x) { - return std_normal_log_qf(x); + static inline auto fun(T&& x) { + return std_normal_log_qf(std::forward(x)); } }; @@ -149,9 +149,10 @@ struct std_normal_log_qf_fun { template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto std_normal_log_qf(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr, require_not_var_matrix_t* = nullptr> +inline auto std_normal_log_qf(T&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } } // namespace math diff --git a/stan/math/rev/fun/exp2.hpp b/stan/math/rev/fun/exp2.hpp index 325fa712b03..20e305d70dd 100644 --- a/stan/math/rev/fun/exp2.hpp +++ b/stan/math/rev/fun/exp2.hpp @@ -36,16 +36,11 @@ namespace math { * @param a The variable. * @return Two to the power of the specified variable. */ -inline var exp2(const var& a) { - return make_callback_var(std::exp2(a.val()), [a](auto& vi) mutable { - a.adj() += vi.adj() * vi.val() * LOG_TWO; - }); -} - -template * = nullptr> -inline auto exp2(const var_value& a) { +template * = nullptr> +inline auto exp2(T&& a) { return make_callback_var(exp2(a.val()), [a](auto& vi) mutable { - a.adj().array() += vi.adj().array() * vi.val().array() * LOG_TWO; + as_array_or_scalar(a.adj()) += as_array_or_scalar(vi.adj()) + * as_array_or_scalar(vi.val()) * LOG_TWO; }); } diff --git a/stan/math/rev/fun/inv.hpp b/stan/math/rev/fun/inv.hpp index 8e920e59925..32e39502cc1 100644 --- a/stan/math/rev/fun/inv.hpp +++ b/stan/math/rev/fun/inv.hpp @@ -27,8 +27,8 @@ namespace math { \f] * */ -template * = nullptr> -inline auto inv(const var_value& a) { +template * = nullptr> +inline auto inv(T&& a) { auto denom = to_arena(as_array_or_scalar(square(a.val()))); return make_callback_var(inv(a.val()), [a, denom](auto& vi) mutable { as_array_or_scalar(a.adj()) -= as_array_or_scalar(vi.adj()) / denom; diff --git a/stan/math/rev/fun/inv_cloglog.hpp b/stan/math/rev/fun/inv_cloglog.hpp index 80789ba01b1..cb5632bd5fd 100644 --- a/stan/math/rev/fun/inv_cloglog.hpp +++ b/stan/math/rev/fun/inv_cloglog.hpp @@ -25,8 +25,8 @@ namespace math { * @return The inverse complementary log-log of the specified * argument. */ -template * = nullptr> -inline auto inv_cloglog(const var_value& a) { +template * = nullptr> +inline auto inv_cloglog(T&& a) { auto precomp_exp = to_arena(as_array_or_scalar(exp(a.val() - exp(a.val())))); return make_callback_var(inv_cloglog(a.val()), [a, precomp_exp](auto& vi) mutable { diff --git a/stan/math/rev/fun/inv_logit.hpp b/stan/math/rev/fun/inv_logit.hpp index ffef93a0256..13b0e051b65 100644 --- a/stan/math/rev/fun/inv_logit.hpp +++ b/stan/math/rev/fun/inv_logit.hpp @@ -22,8 +22,8 @@ namespace math { * @param a Argument variable. * @return Inverse logit of argument. */ -template * = nullptr> -inline auto inv_logit(const var_value& a) { +template * = nullptr> +inline auto inv_logit(T&& a) { return make_callback_var(inv_logit(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a).adj() += as_array_or_scalar(vi.adj()) * as_array_or_scalar(vi.val()) diff --git a/stan/math/rev/fun/inv_sqrt.hpp b/stan/math/rev/fun/inv_sqrt.hpp index 22811e6e189..2ee72ef8ad7 100644 --- a/stan/math/rev/fun/inv_sqrt.hpp +++ b/stan/math/rev/fun/inv_sqrt.hpp @@ -32,8 +32,8 @@ namespace math { \f] * */ -template * = nullptr> -inline auto inv_sqrt(const var_value& a) { +template * = nullptr> +inline auto inv_sqrt(T&& a) { auto denom = to_arena(as_array_or_scalar(a.val()) * as_array_or_scalar(sqrt(a.val()))); return make_callback_var(inv_sqrt(a.val()), [a, denom](auto& vi) mutable { diff --git a/stan/math/rev/fun/inv_square.hpp b/stan/math/rev/fun/inv_square.hpp index de9f1f7663f..c31f10860de 100644 --- a/stan/math/rev/fun/inv_square.hpp +++ b/stan/math/rev/fun/inv_square.hpp @@ -34,6 +34,11 @@ inline var inv_square(const var& a) { }); } +template * = nullptr> +inline auto inv_square(T&& a) { + return inv(square(std::forward(a))); +} + } // namespace math } // namespace stan #endif diff --git a/stan/math/rev/fun/lambert_w.hpp b/stan/math/rev/fun/lambert_w.hpp index f7aafc7c4a2..3fec7998062 100644 --- a/stan/math/rev/fun/lambert_w.hpp +++ b/stan/math/rev/fun/lambert_w.hpp @@ -18,8 +18,8 @@ namespace math { * @param a Variable argument. * @return the Lambert W function (W0 branch) applied to the specified argument. */ -template * = nullptr> -inline auto lambert_w0(const var_value& a) { +template * = nullptr> +inline auto lambert_w0(T&& a) { return make_callback_var(lambert_w0(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += (as_array_or_scalar(vi.adj()) @@ -36,8 +36,8 @@ inline auto lambert_w0(const var_value& a) { * @return the Lambert W function (W-1 branch) applied to the specified * argument. */ -template * = nullptr> -inline auto lambert_wm1(const var_value& a) { +template * = nullptr> +inline auto lambert_wm1(T&& a) { return make_callback_var(lambert_wm1(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += (as_array_or_scalar(vi.adj()) diff --git a/stan/math/rev/fun/lgamma.hpp b/stan/math/rev/fun/lgamma.hpp index 1215f331ba8..0e220088e60 100644 --- a/stan/math/rev/fun/lgamma.hpp +++ b/stan/math/rev/fun/lgamma.hpp @@ -20,8 +20,8 @@ namespace math { * @param a The variable. * @return Log gamma of the variable. */ -template * = nullptr> -inline auto lgamma(const var_value& a) { +template * = nullptr> +inline auto lgamma(T&& a) { return make_callback_var(lgamma(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += as_array_or_scalar(vi.adj()) * as_array_or_scalar(digamma(a.val())); diff --git a/stan/math/rev/fun/log.hpp b/stan/math/rev/fun/log.hpp index ac22788aa96..79939cd13fd 100644 --- a/stan/math/rev/fun/log.hpp +++ b/stan/math/rev/fun/log.hpp @@ -47,8 +47,8 @@ namespace math { * @param a Variable whose log is taken. * @return Natural log of variable. */ -template * = nullptr> -inline auto log(const var_value& a) { +template * = nullptr> +inline auto log(T&& a) { return make_callback_var(log(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += as_array_or_scalar(vi.adj()) / as_array_or_scalar(a.val()); diff --git a/stan/math/rev/fun/log10.hpp b/stan/math/rev/fun/log10.hpp index 82d7884bce7..fd37b97d7a4 100644 --- a/stan/math/rev/fun/log10.hpp +++ b/stan/math/rev/fun/log10.hpp @@ -44,8 +44,8 @@ namespace math { * @param a Variable whose log is taken. * @return Base 10 log of variable. */ -template * = nullptr> -inline auto log10(const var_value& a) { +template * = nullptr> +inline auto log10(T&& a) { return make_callback_var(log10(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += as_array_or_scalar(vi.adj()) / (LOG_TEN * as_array_or_scalar(a.val())); diff --git a/stan/math/rev/fun/log1m.hpp b/stan/math/rev/fun/log1m.hpp index 751ff99e28b..3f256093639 100644 --- a/stan/math/rev/fun/log1m.hpp +++ b/stan/math/rev/fun/log1m.hpp @@ -19,8 +19,8 @@ namespace math { * @param a The variable. * @return The variable representing log of 1 minus the variable. */ -template * = nullptr> -inline auto log1m(const var_value& a) { +template * = nullptr> +inline auto log1m(T&& a) { return make_callback_var(log1m(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += as_array_or_scalar(vi.adj()) / (as_array_or_scalar(a.val()) - 1.0); diff --git a/stan/math/rev/fun/log1m_exp.hpp b/stan/math/rev/fun/log1m_exp.hpp index 4288b945563..6601c6b816a 100644 --- a/stan/math/rev/fun/log1m_exp.hpp +++ b/stan/math/rev/fun/log1m_exp.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace stan { @@ -21,8 +22,8 @@ namespace math { * @return Natural logarithm of one minus the exponential of the * argument. */ -template * = nullptr> -inline auto log1m_exp(const var_value& x) { +template * = nullptr> +inline auto log1m_exp(T&& x) { return make_callback_var(log1m_exp(x.val()), [x](auto& vi) mutable { as_array_or_scalar(x.adj()) -= as_array_or_scalar(vi.adj()) / as_array_or_scalar(expm1(-x.val())); diff --git a/stan/math/rev/fun/log1m_inv_logit.hpp b/stan/math/rev/fun/log1m_inv_logit.hpp index 382878317f3..fafefcb4c66 100644 --- a/stan/math/rev/fun/log1m_inv_logit.hpp +++ b/stan/math/rev/fun/log1m_inv_logit.hpp @@ -17,8 +17,8 @@ namespace math { * @param u argument * @return log of one minus the inverse logit of the argument */ -template * = nullptr> -inline auto log1m_inv_logit(const var_value& u) { +template * = nullptr> +inline auto log1m_inv_logit(T&& u) { auto precomp_inv_logit = to_arena(as_array_or_scalar(-inv_logit(u.val()))); return make_callback_var( log1m_inv_logit(u.val()), [u, precomp_inv_logit](auto& vi) mutable { diff --git a/stan/math/rev/fun/log1p.hpp b/stan/math/rev/fun/log1p.hpp index dc83088d5c2..91a11d4857d 100644 --- a/stan/math/rev/fun/log1p.hpp +++ b/stan/math/rev/fun/log1p.hpp @@ -19,8 +19,8 @@ namespace math { * @param a The variable. * @return The log of 1 plus the variable. */ -template * = nullptr> -inline auto log1p(const var_value& a) { +template * = nullptr> +inline auto log1p(T&& a) { return make_callback_var(log1p(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += as_array_or_scalar(vi.adj()) / (1.0 + as_array_or_scalar(a.val())); diff --git a/stan/math/rev/fun/log1p_exp.hpp b/stan/math/rev/fun/log1p_exp.hpp index f2b24bba3e5..141a2dce1c0 100644 --- a/stan/math/rev/fun/log1p_exp.hpp +++ b/stan/math/rev/fun/log1p_exp.hpp @@ -15,8 +15,8 @@ namespace math { * @tparam T Arithmetic or a type inheriting from `EigenBase`. * @param a The variable. */ -template * = nullptr> -inline auto log1p_exp(const var_value& a) { +template * = nullptr> +inline auto log1p_exp(T&& a) { auto precomp_inv_logit = to_arena(as_array_or_scalar(inv_logit(a.val()))); return make_callback_var( log1p_exp(a.val()), [a, precomp_inv_logit](auto& vi) mutable { diff --git a/stan/math/rev/fun/log2.hpp b/stan/math/rev/fun/log2.hpp index ba9f3faf0f3..c18e8209dc1 100644 --- a/stan/math/rev/fun/log2.hpp +++ b/stan/math/rev/fun/log2.hpp @@ -40,8 +40,8 @@ namespace math { * @param a The variable. * @return Base 2 logarithm of the variable. */ -template * = nullptr> -inline auto log2(const var_value& a) { +template * = nullptr> +inline auto log2(T&& a) { return make_callback_var(log2(a.val()), [a](auto& vi) mutable { as_array_or_scalar(a.adj()) += as_array_or_scalar(vi.adj()) / (LOG_TWO * as_array_or_scalar(a.val())); diff --git a/stan/math/rev/fun/log_softmax.hpp b/stan/math/rev/fun/log_softmax.hpp index d41a567156b..9fddcbf8545 100644 --- a/stan/math/rev/fun/log_softmax.hpp +++ b/stan/math/rev/fun/log_softmax.hpp @@ -120,9 +120,10 @@ inline auto log_softmax(const T& x) { * @throw std::domain_error if the input size is 0 */ template * = nullptr> -inline auto log_softmax(const T& x) { - return apply_vector_unary::apply( - x, [](const auto& alpha) { return log_softmax(alpha); }); +inline auto log_softmax(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](auto&& alpha) { + return log_softmax(std::forward(alpha)); + }); } } // namespace math diff --git a/stan/math/rev/fun/log_sum_exp.hpp b/stan/math/rev/fun/log_sum_exp.hpp index 69299560616..598aa3c502b 100644 --- a/stan/math/rev/fun/log_sum_exp.hpp +++ b/stan/math/rev/fun/log_sum_exp.hpp @@ -99,9 +99,10 @@ inline var log_sum_exp(const T& x) { * @param x matrix */ template * = nullptr> -inline auto log_sum_exp(const T& x) { - return apply_vector_unary::reduce( - x, [](const auto& v) { return log_sum_exp(v); }); +inline auto log_sum_exp(T&& x) { + return apply_vector_unary::reduce(std::forward(x), [](auto&& v) { + return log_sum_exp(std::forward(v)); + }); } } // namespace math diff --git a/stan/math/rev/fun/logit.hpp b/stan/math/rev/fun/logit.hpp index eb88c303687..be4e0d602ea 100644 --- a/stan/math/rev/fun/logit.hpp +++ b/stan/math/rev/fun/logit.hpp @@ -16,8 +16,8 @@ namespace math { * @param u The variable. * @return log odds of argument */ -template * = nullptr> -inline auto logit(const var_value& u) { +template * = nullptr> +inline auto logit(T&& u) { auto denom = to_arena(1.0 / as_array_or_scalar(u.val() - square(u.val()))); return make_callback_var(logit(u.val()), [u, denom](auto& vi) mutable { as_array_or_scalar(u.adj()) += as_array_or_scalar(vi.adj()) * denom; diff --git a/stan/math/rev/fun/norm1.hpp b/stan/math/rev/fun/norm1.hpp index 0bf8c9fa334..f95f079e54b 100644 --- a/stan/math/rev/fun/norm1.hpp +++ b/stan/math/rev/fun/norm1.hpp @@ -15,17 +15,18 @@ namespace math { /** * Returns the L1 norm of a vector of var. * - * @tparam T type of the vector (must have one compile-time dimension equal to - * 1) - * @param[in] v Vector. - * @return L1 norm of v. + * @tparam Container type of the vector (must have one compile-time dimension + * equal to 1) + * @param[in] x Vector. + * @return L1 norm of x. */ -template * = nullptr> -inline var norm1(const T& v) { - arena_t arena_v = v; - var res = norm1(arena_v.val()); - reverse_pass_callback([res, arena_v]() mutable { - arena_v.adj().array() += res.adj() * sign(arena_v.val().array()); +template * = nullptr> +inline var norm1(const Container& x) { + arena_t arena_x = x; + var res = norm1(arena_x.val()); + reverse_pass_callback([res, arena_x]() mutable { + arena_x.adj().array() += res.adj() * sign(arena_x.val().array()); }); return res; } @@ -34,14 +35,14 @@ inline var norm1(const T& v) { * Returns the L1 norm of a `var_value`. * * @tparam A `var_value<>` whose inner type has one compile-time row or column. - * @param[in] v Vector. - * @return L1 norm of v. + * @param[in] x Vector. + * @return L1 norm of x. */ // -template * = nullptr> -inline var norm1(const T& v) { - return make_callback_vari(norm1(v.val()), [v](const auto& res) mutable { - v.adj().array() += res.adj() * sign(v.val().array()); +template * = nullptr> +inline var norm1(const Container& x) { + return make_callback_vari(norm1(x.val()), [x](const auto& res) mutable { + x.adj().array() += res.adj() * sign(x.val().array()); }); } diff --git a/stan/math/rev/fun/norm2.hpp b/stan/math/rev/fun/norm2.hpp index f3599c1e693..0415f2bfeaf 100644 --- a/stan/math/rev/fun/norm2.hpp +++ b/stan/math/rev/fun/norm2.hpp @@ -14,17 +14,18 @@ namespace math { /** * Returns the L2 norm of a vector of var. * - * @tparam T type of the vector (must have one compile-time dimension equal to - * 1) - * @param[in] v Vector. - * @return L2 norm of v. + * @tparam Container type of the vector (must have one compile-time dimension + * equal to 1) + * @param[in] x Vector. + * @return L2 norm of x. */ -template * = nullptr> -inline var norm2(const T& v) { - arena_t arena_v = v; - var res = norm2(arena_v.val()); - reverse_pass_callback([res, arena_v]() mutable { - arena_v.adj().array() += res.adj() * (arena_v.val().array() / res.val()); +template * = nullptr> +inline var norm2(const Container& x) { + arena_t arena_x = x; + var res = norm2(arena_x.val()); + reverse_pass_callback([res, arena_x]() mutable { + arena_x.adj().array() += res.adj() * (arena_x.val().array() / res.val()); }); return res; } @@ -32,14 +33,15 @@ inline var norm2(const T& v) { /** * Returns the L2 norm of a `var_value`. * - * @tparam A `var_value<>` whose inner type has one compile-time row or column. - * @param[in] v Vector. - * @return L2 norm of v. + * @tparam Container `var_value<>` whose inner type has one compile-time row or + * column. + * @param[in] x Vector. + * @return L2 norm of x. */ -template * = nullptr> -inline var norm2(const T& v) { - return make_callback_vari(norm2(v.val()), [v](const auto& res) mutable { - v.adj().array() += res.adj() * (v.val().array() / res.val()); +template * = nullptr> +inline var norm2(const Container& x) { + return make_callback_vari(norm2(x.val()), [x](const auto& res) mutable { + x.adj().array() += res.adj() * (x.val().array() / res.val()); }); } diff --git a/stan/math/rev/fun/pow.hpp b/stan/math/rev/fun/pow.hpp index d525e00a04b..641272bd9cf 100644 --- a/stan/math/rev/fun/pow.hpp +++ b/stan/math/rev/fun/pow.hpp @@ -287,9 +287,13 @@ inline auto pow(Scal1 base, const Mat1& exponent) { template * = nullptr, require_all_not_matrix_st* = nullptr, require_any_var_t, base_type_t>* = nullptr> -inline auto pow(const T1& a, const T2& b) { +inline auto pow(T1&& a, T2&& b) { return apply_scalar_binary( - [](const auto& c, const auto& d) { return stan::math::pow(c, d); }, a, b); + [](auto&& c, auto&& d) { + return stan::math::pow(std::forward(c), + std::forward(d)); + }, + std::forward(a), std::forward(b)); } } // namespace math diff --git a/stan/math/rev/fun/sd.hpp b/stan/math/rev/fun/sd.hpp index e3db2d1651f..b5be0261467 100644 --- a/stan/math/rev/fun/sd.hpp +++ b/stan/math/rev/fun/sd.hpp @@ -94,8 +94,10 @@ var sd(const T& x) { * @throw domain error size is not greater than zero. */ template * = nullptr> -auto sd(const T& m) { - return apply_vector_unary::reduce(m, [](const auto& x) { return sd(x); }); +auto sd(T&& m) { + return apply_vector_unary::reduce(std::forward(m), [](auto&& x) { + return sd(std::forward(x)); + }); } } // namespace math diff --git a/stan/math/rev/functor/apply_scalar_binary.hpp b/stan/math/rev/functor/apply_scalar_binary.hpp index a1f20d7caaf..48e4479e3f3 100644 --- a/stan/math/rev/functor/apply_scalar_binary.hpp +++ b/stan/math/rev/functor/apply_scalar_binary.hpp @@ -28,9 +28,9 @@ namespace math { template * = nullptr, require_all_matrix_t* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { check_matching_dims("Binary function", "x", x, "y", y); - return f(x, y); + return std::forward(f)(std::forward(x), std::forward(y)); } /** @@ -48,9 +48,9 @@ inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { template * = nullptr, require_any_std_vector_vt* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { check_matching_sizes("Binary function", "x", x, "y", y); - return f(x, y); + return std::forward(f)(std::forward(x), std::forward(y)); } /** @@ -71,8 +71,8 @@ template * = nullptr, require_any_std_vector_st* = nullptr, require_any_var_matrix_t* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { - return f(x, y); +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { + return std::forward(f)(std::forward(x), std::forward(y)); } /** @@ -93,8 +93,8 @@ inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { template * = nullptr, require_any_var_matrix_t* = nullptr> -inline auto apply_scalar_binary(const F& f, const T1& x, const T2& y) { - return f(x, y); +inline auto apply_scalar_binary(F&& f, T1&& x, T2&& y) { + return std::forward(f)(std::forward(x), std::forward(y)); } } // namespace math diff --git a/stan/math/rev/functor/apply_scalar_unary.hpp b/stan/math/rev/functor/apply_scalar_unary.hpp index d68bd344335..338350dd5bd 100644 --- a/stan/math/rev/functor/apply_scalar_unary.hpp +++ b/stan/math/rev/functor/apply_scalar_unary.hpp @@ -15,8 +15,9 @@ namespace math { * * @tparam F Type of function to apply. */ -template -struct apply_scalar_unary { +template +struct apply_scalar_unary< + F, T, std::enable_if_t::value && is_stan_scalar::value>> { /** * Function return type, which is var. */ @@ -28,7 +29,10 @@ struct apply_scalar_unary { * @param x Argument variable. * @return Function applied to the variable. */ - static inline return_t apply(const var& x) { return F::fun(x); } + template + static inline auto apply(T2&& x) { + return F::fun(std::forward(x)); + } }; template @@ -44,7 +48,10 @@ struct apply_scalar_unary> { * @param x Argument variable. * @return Function applied to the variable. */ - static inline return_t apply(const T& x) { return F::fun(x); } + template + static inline auto apply(T2&& x) { + return F::fun(std::forward(x)); + } }; } // namespace math diff --git a/stan/math/rev/functor/apply_vector_unary.hpp b/stan/math/rev/functor/apply_vector_unary.hpp index 01cad885a70..af5627dfdde 100644 --- a/stan/math/rev/functor/apply_vector_unary.hpp +++ b/stan/math/rev/functor/apply_vector_unary.hpp @@ -24,9 +24,9 @@ struct apply_vector_unary> { * @param f functor to apply to Eigen input. * @return object with result of applying functor to input */ - template - static inline plain_type_t apply(const T& x, const F& f) { - return f(x); + template + static inline auto apply(T2&& x, F&& f) { + return std::forward(f)(std::forward(x)); } /** @@ -39,9 +39,9 @@ struct apply_vector_unary> { * @param f functor to apply to Eigen input. * @return object with result of applying functor to input */ - template - static inline plain_type_t apply_no_holder(const T& x, const F& f) { - return f(x); + template + static inline auto apply_no_holder(T2&& x, F&& f) { + return std::forward(f)(std::forward(x)); } /** @@ -55,9 +55,9 @@ struct apply_vector_unary> { * @param f functor to apply to input. * @return scalar result of applying functor to input. */ - template - static inline var reduce(const T& x, const F& f) { - return f(x); + template + static inline auto reduce(T2& x, F&& f) { + return std::forward(f)(std::forward(x)); } }; diff --git a/stan/math/rev/prob/std_normal_log_qf.hpp b/stan/math/rev/prob/std_normal_log_qf.hpp index b230f3ea872..6578f301adf 100644 --- a/stan/math/rev/prob/std_normal_log_qf.hpp +++ b/stan/math/rev/prob/std_normal_log_qf.hpp @@ -17,8 +17,8 @@ namespace math { * @param log_p log probability vector * @return Elementwise unit normal inverse cdf */ -template * = nullptr> -inline auto std_normal_log_qf(const var_value& log_p) { +template * = nullptr> +inline auto std_normal_log_qf(T&& log_p) { auto arena_rtn = to_arena(std_normal_log_qf(log_p.val())); return make_callback_var(arena_rtn, [log_p, arena_rtn](auto& vi) mutable { if constexpr (is_eigen::value) { diff --git a/test/prob/chi_square/chi_square_test.hpp b/test/prob/chi_square/chi_square_test.hpp index e42289c5a39..8fe5126c8d7 100644 --- a/test/prob/chi_square/chi_square_test.hpp +++ b/test/prob/chi_square/chi_square_test.hpp @@ -60,10 +60,9 @@ class AgradDistributionsChiSquare : public AgradDistributionTest { const T_dof& nu, const T2&, const T3&, const T4&, const T5&) { - using boost::math::lgamma; using stan::math::HALF_LOG_TWO; + using stan::math::lgamma; using stan::math::multiply_log; - return -nu * HALF_LOG_TWO - lgamma(0.5 * nu) + multiply_log(0.5 * nu - 1.0, y) - 0.5 * y; } diff --git a/test/prob/gamma/gamma_ccdf_log_test.hpp b/test/prob/gamma/gamma_ccdf_log_test.hpp index 35ef3951c1a..abc0fea853e 100644 --- a/test/prob/gamma/gamma_ccdf_log_test.hpp +++ b/test/prob/gamma/gamma_ccdf_log_test.hpp @@ -92,7 +92,6 @@ class AgradCcdfLogGamma : public AgradCcdfLogTest { stan::return_type_t ccdf_log_function( const T_y& y, const T_shape& alpha, const T_inv_scale& beta, const T3&, const T4&, const T5&) { - using boost::math::gamma_p; using stan::math::gamma_p; using stan::math::log1m; diff --git a/test/prob/gamma/gamma_cdf_log_test.hpp b/test/prob/gamma/gamma_cdf_log_test.hpp index 1a67584510d..24cf75eb1d7 100644 --- a/test/prob/gamma/gamma_cdf_log_test.hpp +++ b/test/prob/gamma/gamma_cdf_log_test.hpp @@ -83,7 +83,6 @@ class AgradCdfLogGamma : public AgradCdfLogTest { stan::return_type_t cdf_log_function( const T_y& y, const T_shape& alpha, const T_inv_scale& beta, const T3&, const T4&, const T5&) { - using boost::math::gamma_p; using stan::math::gamma_p; using std::log; diff --git a/test/prob/gamma/gamma_cdf_test.hpp b/test/prob/gamma/gamma_cdf_test.hpp index 613dbececf9..29290af93cc 100644 --- a/test/prob/gamma/gamma_cdf_test.hpp +++ b/test/prob/gamma/gamma_cdf_test.hpp @@ -83,7 +83,6 @@ class AgradCdfGamma : public AgradCdfTest { stan::return_type_t cdf_function( const T_y& y, const T_shape& alpha, const T_inv_scale& beta, const T3&, const T4&, const T5&) { - using boost::math::gamma_p; using stan::math::gamma_p; return gamma_p(alpha, beta * y); diff --git a/test/prob/inv_chi_square/inv_chi_square_test.hpp b/test/prob/inv_chi_square/inv_chi_square_test.hpp index 523f94049d4..ebabb40da1d 100644 --- a/test/prob/inv_chi_square/inv_chi_square_test.hpp +++ b/test/prob/inv_chi_square/inv_chi_square_test.hpp @@ -61,10 +61,9 @@ class AgradDistributionsInvChiSquare : public AgradDistributionTest { const T_dof& nu, const T2&, const T3&, const T4&, const T5&) { - using boost::math::lgamma; using stan::math::HALF_LOG_TWO; + using stan::math::lgamma; using stan::math::multiply_log; - return -nu * HALF_LOG_TWO - lgamma(0.5 * nu) - multiply_log(0.5 * nu + 1.0, y) - 0.5 / y; } diff --git a/test/prob/inv_gamma/inv_gamma_test.hpp b/test/prob/inv_gamma/inv_gamma_test.hpp index 9d8565a2eb1..6e48567f406 100644 --- a/test/prob/inv_gamma/inv_gamma_test.hpp +++ b/test/prob/inv_gamma/inv_gamma_test.hpp @@ -84,9 +84,8 @@ class AgradDistributionsInvGamma : public AgradDistributionTest { if (y <= 0) return stan::math::LOG_ZERO; - using boost::math::lgamma; + using stan::math::lgamma; using stan::math::multiply_log; - return -lgamma(alpha) + multiply_log(alpha, beta) - multiply_log(alpha + 1.0, y) - beta / y; } diff --git a/test/prob/poisson/poisson_ccdf_log_test.hpp b/test/prob/poisson/poisson_ccdf_log_test.hpp index 8accc19faf5..3ddca995049 100644 --- a/test/prob/poisson/poisson_ccdf_log_test.hpp +++ b/test/prob/poisson/poisson_ccdf_log_test.hpp @@ -60,7 +60,6 @@ class AgradCcdfLogPoisson : public AgradCcdfLogTest { const T_rate& lambda, const T2&, const T3&, const T4&, const T5&) { - using boost::math::lgamma; using stan::math::exp; using stan::math::lgamma; using stan::math::log; diff --git a/test/prob/poisson/poisson_cdf_log_test.hpp b/test/prob/poisson/poisson_cdf_log_test.hpp index 2e989135283..52ecd191428 100644 --- a/test/prob/poisson/poisson_cdf_log_test.hpp +++ b/test/prob/poisson/poisson_cdf_log_test.hpp @@ -57,7 +57,6 @@ class AgradCdfLogPoisson : public AgradCdfLogTest { const T_rate& lambda, const T2&, const T3&, const T4&, const T5&) { - using boost::math::lgamma; using stan::math::exp; using stan::math::lgamma; using stan::math::log; diff --git a/test/prob/poisson/poisson_cdf_test.hpp b/test/prob/poisson/poisson_cdf_test.hpp index aae9f23398b..cb2ef4a1b74 100644 --- a/test/prob/poisson/poisson_cdf_test.hpp +++ b/test/prob/poisson/poisson_cdf_test.hpp @@ -54,7 +54,6 @@ class AgradCdfPoisson : public AgradCdfTest { stan::return_type_t cdf_function(const T_n& n, const T_rate& lambda, const T2&, const T3&, const T4&, const T5&) { - using boost::math::lgamma; using stan::math::exp; using stan::math::lgamma; using stan::math::log; @@ -62,7 +61,7 @@ class AgradCdfPoisson : public AgradCdfTest { stan::return_type_t cdf(0); for (int i = 0; i <= n; i++) { - cdf += exp(i * log(lambda) - lgamma(i + 1)); + cdf += exp(i * log(lambda) - stan::math::lgamma(i + 1)); } cdf *= exp(-lambda); return cdf; diff --git a/test/prob/poisson/poisson_log_test.hpp b/test/prob/poisson/poisson_log_test.hpp index 7afd0a9d21e..9e83b97fe11 100644 --- a/test/prob/poisson/poisson_log_test.hpp +++ b/test/prob/poisson/poisson_log_test.hpp @@ -63,7 +63,7 @@ class AgradDistributionsPoisson : public AgradDistributionTest { const T_rate& alpha, const T2&, const T3&, const T4&, const T5&) { - using boost::math::lgamma; + using stan::math::lgamma; using stan::math::LOG_ZERO; using stan::math::multiply_log; using std::exp; diff --git a/test/prob/poisson/poisson_test.hpp b/test/prob/poisson/poisson_test.hpp index 57bfb9712ce..2b25bff9aa0 100644 --- a/test/prob/poisson/poisson_test.hpp +++ b/test/prob/poisson/poisson_test.hpp @@ -65,10 +65,9 @@ class AgradDistributionsPoisson : public AgradDistributionTest { const T_rate& lambda, const T2&, const T3&, const T4&, const T5&) { - using boost::math::lgamma; + using stan::math::lgamma; using stan::math::LOG_ZERO; using stan::math::multiply_log; - if (lambda == 0) return n == 0 ? 0 : LOG_ZERO; diff --git a/test/prob/student_t/student_t_test.hpp b/test/prob/student_t/student_t_test.hpp index 914649d5552..05c0e7b5e66 100644 --- a/test/prob/student_t/student_t_test.hpp +++ b/test/prob/student_t/student_t_test.hpp @@ -89,7 +89,7 @@ class AgradDistributionsStudentT : public AgradDistributionTest { stan::return_type_t log_prob_function( const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma, const T4&, const T5&) { - using boost::math::lgamma; + using stan::math::lgamma; using stan::math::log1p; using stan::math::LOG_SQRT_PI; using stan::math::square; diff --git a/test/unit/math/mix/fun/ub_constrain_test.cpp b/test/unit/math/mix/fun/ub_constrain_test.cpp index f3a4f18b569..90ec887fcd2 100644 --- a/test/unit/math/mix/fun/ub_constrain_test.cpp +++ b/test/unit/math/mix/fun/ub_constrain_test.cpp @@ -119,9 +119,9 @@ TEST(mathMixMatFun, ub_stdvec_constrain_inf) { // matrix[], real TEST(mathMixMatFun, ub_stdvec_mat_mat_constrain) { Eigen::MatrixXd A_inner(2, 3); - A_inner << 5.0, 2.0, 4.0, -2.0, 0.0, 0.005; + A_inner << 5.0, 2.0, 4.0, -2.0, 1.0, 2.0; Eigen::MatrixXd ubm_inner(2, 3); - ubm_inner << 7.0, 5.0, 6.0, 100.0, 0.0, 0.0005; + ubm_inner << 7.0, 5.0, 6.0, 100.0, 2.0, 1.0005; Eigen::MatrixXd ubm_inner_bad(2, 1); ubm_inner_bad << 7.0, 5.0; Eigen::MatrixXd A_inner2 = 2.0 * A_inner; diff --git a/test/unit/math/prim/meta/holder_test.cpp b/test/unit/math/prim/meta/holder_test.cpp index 7d43777b1bc..9dee66279db 100644 --- a/test/unit/math/prim/meta/holder_test.cpp +++ b/test/unit/math/prim/meta/holder_test.cpp @@ -134,3 +134,25 @@ TEST(MathFunctions, block_of_make_holder_assign) { EXPECT_MATRIX_EQ(res, m2); EXPECT_MATRIX_EQ(m, m2); } + +TEST(MathFunctions, operations_on_holders) { + Eigen::MatrixXd m1(2, 2); + m1 << 1, 2, 3, 4; + Eigen::MatrixXd m2 = m1; + namespace sm = stan::math; + Eigen::MatrixXd X = sm::subtract(sm::subtract(sm::sin(m1), sm::cos(m2)), m2); + // -- Alias matching your error’s T_ret_col_major + using T_ret_col_major = Eigen::Matrix; + // prepare a small matrix + T_ret_col_major alpha(2, 2); + alpha << 1.0, 2.0, 3.0, 4.0; + + // term2: a plain Eigen matrix + T_ret_col_major m(2, 2); + m << std::lgamma(1.0), std::lgamma(2.0), std::lgamma(3.0), std::lgamma(4.0); + + // ← this line reproduces the compile-error: + // invalid operands to binary expression ('Holder<…>' and + // 'T_ret_col_major') + auto result = m1 - m; +} diff --git a/test/unit/math/prim/prob/skew_double_exponential_ccdf_log_test.cpp b/test/unit/math/prim/prob/skew_double_exponential_ccdf_log_test.cpp index b324b1ca5bd..f1769ee046c 100644 --- a/test/unit/math/prim/prob/skew_double_exponential_ccdf_log_test.cpp +++ b/test/unit/math/prim/prob/skew_double_exponential_ccdf_log_test.cpp @@ -1,15 +1,14 @@ -#include -#include -#include +#include +#include +#include +#include #include #include #include - -#include -#include -#include -#include +#include +#include +#include template inline typename boost::math::tools::promote_args::type @@ -26,53 +25,6 @@ skew_de_ccdf_test(const T1& y, const T2& mu, const T3& sigma, const T4& tau) { } } -TEST(ProbDistributionsSkewedDoubleExponential, - lccdf_computes_correct_gradients) { - using stan::math::skew_double_exponential_lccdf; - - for (double ys : {-1.7, 0.2, 0.5, 0.9, 1.1, 3.2, 8.3}) { - for (double mus : {-1.8, 0.1, 0.55, 0.89, 1.3, 4.2, 9.3}) { - for (double sigmas : {0.1, 0.5, 1.1, 10.1}) { - for (double taus : {0.01, 0.1, 0.5, 0.6, 0.9, 0.99}) { - stan::math::var y = ys; - stan::math::var mu = mus; - stan::math::var sigma = sigmas; - stan::math::var tau = taus; - - stan::math::var lp = skew_double_exponential_lccdf(y, mu, sigma, tau); - std::vector theta; - theta.push_back(y); - theta.push_back(mu); - theta.push_back(sigma); - theta.push_back(tau); - std::vector grads; - lp.grad(theta, grads); - - stan::math::var y_true = ys; - stan::math::var mu_true = mus; - stan::math::var sigma_true = sigmas; - stan::math::var tau_true = taus; - - stan::math::var lp_test - = skew_de_ccdf_test(y_true, mu_true, sigma_true, tau_true); - std::vector theta_true; - theta_true.push_back(y_true); - theta_true.push_back(mu_true); - theta_true.push_back(sigma_true); - theta_true.push_back(tau_true); - std::vector grads_true; - lp_test.grad(theta_true, grads_true); - - EXPECT_NEAR(grads_true[0], grads[0], 0.01); - EXPECT_NEAR(grads_true[1], grads[1], 0.01); - EXPECT_NEAR(grads_true[2], grads[2], 0.01); - EXPECT_NEAR(grads_true[3], grads[3], 0.01); - } - } - } - } -} - TEST(ProbDistributionsSkewedDoubleExponential, lccdf_works_on_scalar_arguments) { using stan::math::skew_double_exponential_lccdf; diff --git a/test/unit/math/rev/prob/skew_double_exponential_ccdf_log_test.cpp b/test/unit/math/rev/prob/skew_double_exponential_ccdf_log_test.cpp new file mode 100644 index 00000000000..3dc41c72845 --- /dev/null +++ b/test/unit/math/rev/prob/skew_double_exponential_ccdf_log_test.cpp @@ -0,0 +1,75 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +template +inline auto skew_de_ccdf_test(const T1& y, const T2& mu, const T3& sigma, + const T4& tau) { + using stan::math::log1m; + using stan::math::log1m_exp; + using std::exp; + using std::log; + + if (y < mu) { + return stan::math::log1m_exp(stan::math::log(tau) + - 2.0 / sigma * (1.0 - tau) * (mu - y)); + } else { + return stan::math::log1m_exp(stan::math::log1m( + (1 - tau) * stan::math::exp(-2 / sigma * tau * (y - mu)))); + } +} + +TEST(RevProbDistributionsSkewedDoubleExponential, + lccdf_computes_correct_gradients) { + using stan::math::skew_double_exponential_lccdf; + + for (double ys : {-1.7, 0.2, 0.5, 0.9, 1.1, 3.2, 8.3}) { + for (double mus : {-1.8, 0.1, 0.55, 0.89, 1.3, 4.2, 9.3}) { + for (double sigmas : {0.1, 0.5, 1.1, 10.1}) { + for (double taus : {0.01, 0.1, 0.5, 0.6, 0.9, 0.99}) { + stan::math::var y = ys; + stan::math::var mu = mus; + stan::math::var sigma = sigmas; + stan::math::var tau = taus; + + stan::math::var lp = skew_double_exponential_lccdf(y, mu, sigma, tau); + std::vector theta; + theta.push_back(y); + theta.push_back(mu); + theta.push_back(sigma); + theta.push_back(tau); + std::vector grads; + lp.grad(theta, grads); + + stan::math::var y_true = ys; + stan::math::var mu_true = mus; + stan::math::var sigma_true = sigmas; + stan::math::var tau_true = taus; + + stan::math::var lp_test + = skew_de_ccdf_test(y_true, mu_true, sigma_true, tau_true); + std::vector theta_true; + theta_true.push_back(y_true); + theta_true.push_back(mu_true); + theta_true.push_back(sigma_true); + theta_true.push_back(tau_true); + std::vector grads_true; + lp_test.grad(theta_true, grads_true); + + EXPECT_NEAR(grads_true[0], grads[0], 0.01); + EXPECT_NEAR(grads_true[1], grads[1], 0.01); + EXPECT_NEAR(grads_true[2], grads[2], 0.01); + EXPECT_NEAR(grads_true[3], grads[3], 0.01); + } + } + } + } +} +} // namespace diff --git a/test/unit/math/test_ad_test.cpp b/test/unit/math/test_ad_test.cpp index 65d42abc3f1..8eb5f4210a6 100644 --- a/test/unit/math/test_ad_test.cpp +++ b/test/unit/math/test_ad_test.cpp @@ -274,8 +274,7 @@ struct baz_fun { }; template -inline typename stan::math::apply_scalar_unary::return_t baz( - const T& x) { +inline auto baz(const T& x) { return stan::math::apply_scalar_unary::apply(x); }