diff --git a/stan/math/fwd/fun/Phi.hpp b/stan/math/fwd/fun/Phi.hpp index 70c1c38249e..042e8222f17 100644 --- a/stan/math/fwd/fun/Phi.hpp +++ b/stan/math/fwd/fun/Phi.hpp @@ -12,10 +12,10 @@ namespace stan { namespace math { -template -inline fvar Phi(const fvar& x) { - T xv = x.val_; - return fvar(Phi(xv), x.d_ * exp(xv * xv / -2.0) * INV_SQRT_TWO_PI); +template * = nullptr> +inline auto Phi(T&& x) { + return std::decay_t(Phi(x.val_), + x.d_ * exp(x.val_ * x.val_ / -2.0) * INV_SQRT_TWO_PI); } } // namespace math diff --git a/stan/math/fwd/fun/cbrt.hpp b/stan/math/fwd/fun/cbrt.hpp index bfdec65d9c9..8b915006dcb 100644 --- a/stan/math/fwd/fun/cbrt.hpp +++ b/stan/math/fwd/fun/cbrt.hpp @@ -16,9 +16,9 @@ namespace math { * @param x Argument. * @return Cube root of argument. */ -template -inline fvar cbrt(const fvar& x) { - return fvar(cbrt(x.val_), x.d_ / (3 * square(cbrt(x.val_)))); +template * = nullptr> +inline auto cbrt(T&& x) { + return std::decay_t(cbrt(x.val_), x.d_ / (3 * square(cbrt(x.val_)))); } } // namespace math diff --git a/stan/math/fwd/fun/digamma.hpp b/stan/math/fwd/fun/digamma.hpp index ede447b685a..4f49be49378 100644 --- a/stan/math/fwd/fun/digamma.hpp +++ b/stan/math/fwd/fun/digamma.hpp @@ -4,7 +4,6 @@ #include #include #include - #include namespace stan { @@ -19,9 +18,9 @@ namespace math { * @return derivative of the log gamma function at the specified * argument */ -template -inline fvar digamma(const fvar& x) { - return fvar(digamma(x.val_), x.d_ * trigamma(x.val_)); +template * = nullptr> +inline auto digamma(T&& x) { + return std::decay_t(digamma(x.val_), x.d_ * trigamma(x.val_)); } } // namespace math diff --git a/stan/math/fwd/fun/log_softmax.hpp b/stan/math/fwd/fun/log_softmax.hpp index 82d1f7b0204..609fb0daeb8 100644 --- a/stan/math/fwd/fun/log_softmax.hpp +++ b/stan/math/fwd/fun/log_softmax.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace stan { namespace math { @@ -19,24 +20,24 @@ 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) { +inline auto log_softmax(T&& x) { + return apply_vector_unary::apply(std::forward(x), [](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); + auto&& alpha_ref = to_ref(std::forward(alpha)); + Eigen::Matrix alpha_v = alpha_ref.val(); + Eigen::Matrix softmax_alpha_v = softmax(alpha_v); - Eigen::Matrix log_softmax_alpha(alpha.size()); - log_softmax_alpha.val() = log_softmax(alpha_t); + Eigen::Matrix log_softmax_alpha(alpha_ref.size()); + log_softmax_alpha.val() = log_softmax(alpha_v); log_softmax_alpha.d().setZero(); - for (int m = 0; m < alpha.size(); ++m) { + for (int m = 0; m < alpha_ref.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) { + = -alpha_ref.coeff(m).d_ * softmax_alpha_v(m); + for (int k = 0; k < alpha_ref.size(); ++k) { if (m == k) { log_softmax_alpha(k).d_ += alpha_ref.coeff(m).d_ 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..a4026988dee 100644 --- a/stan/math/fwd/fun/norm1.hpp +++ b/stan/math/fwd/fun/norm1.hpp @@ -20,9 +20,9 @@ namespace math { * @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..61129a3709b 100644 --- a/stan/math/fwd/fun/norm2.hpp +++ b/stan/math/fwd/fun/norm2.hpp @@ -19,9 +19,9 @@ namespace math { * @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/prim/constraint/cholesky_corr_constrain.hpp b/stan/math/prim/constraint/cholesky_corr_constrain.hpp index 3a55e04b3f2..9f489dc08f7 100644 --- a/stan/math/prim/constraint/cholesky_corr_constrain.hpp +++ b/stan/math/prim/constraint/cholesky_corr_constrain.hpp @@ -14,7 +14,7 @@ namespace math { template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cholesky_corr_constrain(const EigVec& y, int K) { +cholesky_corr_constrain(EigVec&& y, int K) { using Eigen::Dynamic; using Eigen::Matrix; using std::sqrt; @@ -22,7 +22,7 @@ cholesky_corr_constrain(const EigVec& y, int K) { int k_choose_2 = (K * (K - 1)) / 2; check_size_match("cholesky_corr_constrain", "constrain size", y.size(), "k_choose_2", k_choose_2); - Matrix z = corr_constrain(y); + Matrix z = corr_constrain(std::forward(y)); Matrix x(K, K); if (K == 0) { return x; @@ -47,7 +47,7 @@ template * = nullptr, require_convertible_t, Lp>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cholesky_corr_constrain(const EigVec& y, int K, Lp& lp) { +cholesky_corr_constrain(EigVec&& y, int K, Lp& lp) { using Eigen::Dynamic; using Eigen::Matrix; using std::sqrt; @@ -55,7 +55,7 @@ cholesky_corr_constrain(const EigVec& y, int K, Lp& lp) { int k_choose_2 = (K * (K - 1)) / 2; check_size_match("cholesky_corr_constrain", "y.size()", y.size(), "k_choose_2", k_choose_2); - Matrix z = corr_constrain(y, lp); + Matrix z = corr_constrain(std::forward(y), lp); Matrix x(K, K); if (K == 0) { return x; @@ -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..1f93fb3d965 100644 --- a/stan/math/prim/constraint/cholesky_corr_free.hpp +++ b/stan/math/prim/constraint/cholesky_corr_free.hpp @@ -11,7 +11,7 @@ namespace stan { namespace math { template * = nullptr> -inline auto cholesky_corr_free(const T& x) { +inline auto cholesky_corr_free(T&& x) { using Eigen::Dynamic; using Eigen::Matrix; using std::sqrt; @@ -19,11 +19,11 @@ inline auto cholesky_corr_free(const T& x) { check_square("cholesky_corr_free", "x", x); // should validate lower-triangular, unit lengths - const auto& x_ref = to_ref(x); - int K = (x.rows() * (x.rows() - 1)) / 2; + auto&& x_ref = to_ref(std::forward(x)); + int K = (x_ref.rows() * (x_ref.rows() - 1)) / 2; Matrix, Dynamic, 1> z(K); int k = 0; - for (int i = 1; i < x.rows(); ++i) { + for (int i = 1; i < x_ref.rows(); ++i) { z.coeffRef(k++) = corr_free(x_ref.coeff(i, 0)); auto sum_sqs = square(x_ref.coeff(i, 0)); for (int j = 1; j < i; ++j) { @@ -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..056871f23be 100644 --- a/stan/math/prim/constraint/cholesky_factor_constrain.hpp +++ b/stan/math/prim/constraint/cholesky_factor_constrain.hpp @@ -27,7 +27,7 @@ namespace math { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cholesky_factor_constrain(const T& x, int M, int N) { +cholesky_factor_constrain(T&& x, int M, int N) { using std::exp; using T_scalar = value_type_t; check_greater_or_equal("cholesky_factor_constrain", @@ -39,7 +39,7 @@ cholesky_factor_constrain(const T& x, int M, int N) { Eigen::Matrix y(M, N); int pos = 0; - const auto& x_ref = to_ref(x); + auto&& x_ref = to_ref(std::forward(x)); for (int m = 0; m < N; ++m) { y.row(m).head(m) = x_ref.segment(pos, m); pos += m; @@ -73,17 +73,17 @@ cholesky_factor_constrain(const T& x, int M, int N) { template * = nullptr, require_convertible_t, Lp>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cholesky_factor_constrain(const T& x, int M, int N, Lp& lp) { +cholesky_factor_constrain(T&& x, int M, int N, Lp& lp) { check_size_match("cholesky_factor_constrain", "x.size()", x.size(), "((N * (N + 1)) / 2 + (M - N) * N)", ((N * (N + 1)) / 2 + (M - N) * N)); int pos = 0; - const auto& x_ref = to_ref(x); + auto&& x_ref = to_ref(std::forward(x)); for (int n = 0; n < N; ++n) { pos += n; lp += x_ref.coeff(pos++); } - return cholesky_factor_constrain(x_ref, M, N); + return cholesky_factor_constrain(std::forward(x_ref), M, N); } /** @@ -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..8b9a39bb548 100644 --- a/stan/math/prim/constraint/cholesky_factor_free.hpp +++ b/stan/math/prim/constraint/cholesky_factor_free.hpp @@ -23,25 +23,24 @@ namespace math { * @throw std::domain_error If the matrix is not a Cholesky factor. */ template * = nullptr> -Eigen::Matrix, Eigen::Dynamic, 1> cholesky_factor_free( - const T& y) { +Eigen::Matrix, Eigen::Dynamic, 1> cholesky_factor_free(T&& y) { using std::log; - const auto& y_ref = to_ref(y); + auto&& y_ref = to_ref(std::forward(y)); check_cholesky_factor("cholesky_factor_free", "y", y_ref); - int M = y.rows(); - int N = y.cols(); + const auto M = y_ref.rows(); + const auto N = y_ref.cols(); Eigen::Matrix, Eigen::Dynamic, 1> x((N * (N + 1)) / 2 + (M - N) * N); - int pos = 0; + Eigen::Index pos = 0; - for (int m = 0; m < N; ++m) { + for (Eigen::Index m = 0; m < N; ++m) { x.segment(pos, m) = y_ref.row(m).head(m); pos += m; x.coeffRef(pos++) = log(y_ref.coeff(m, m)); } - for (int m = N; m < M; ++m) { + for (Eigen::Index m = N; m < M; ++m) { x.segment(pos, N) = y_ref.row(m); pos += N; } @@ -56,9 +55,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..5e0b542c758 100644 --- a/stan/math/prim/constraint/corr_free.hpp +++ b/stan/math/prim/constraint/corr_free.hpp @@ -25,9 +25,9 @@ namespace math { * @return free scalar that transforms to the specified input */ template -inline plain_type_t corr_free(const T& y) { +inline plain_type_t corr_free(T&& y) { check_bounded("lub_free", "Correlation variable", y, -1.0, 1.0); - return atanh(y); + return atanh(std::forward(y)); } } // namespace math diff --git a/stan/math/prim/constraint/corr_matrix_constrain.hpp b/stan/math/prim/constraint/corr_matrix_constrain.hpp index 060b1d5f6a3..36ded2854ca 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) { - Eigen::Index k_choose_2 = (k * (k - 1)) / 2; +corr_matrix_constrain(T&& x, Eigen::Index k) { + const 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) { - Eigen::Index k_choose_2 = (k * (k - 1)) / 2; +corr_matrix_constrain(T&& x, Eigen::Index k, Lp& lp) { + const 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..1c7046767db 100644 --- a/stan/math/prim/constraint/corr_matrix_free.hpp +++ b/stan/math/prim/constraint/corr_matrix_free.hpp @@ -31,7 +31,7 @@ namespace math { * factor_cov_matrix() on log scale are unconstrained. */ template * = nullptr> -Eigen::Matrix, Eigen::Dynamic, 1> corr_matrix_free(const T& y) { +Eigen::Matrix, Eigen::Dynamic, 1> corr_matrix_free(T&& y) { using Eigen::Array; using Eigen::Dynamic; @@ -42,7 +42,7 @@ Eigen::Matrix, Eigen::Dynamic, 1> corr_matrix_free(const T& y) { Eigen::Index k_choose_2 = (k * (k - 1)) / 2; Eigen::Matrix, Dynamic, 1> x(k_choose_2); Array, Dynamic, 1> sds(k); - bool successful = factor_cov_matrix(y, x.array(), sds); + bool successful = factor_cov_matrix(std::forward(y), x.array(), sds); if (!successful) { throw_domain_error("corr_matrix_free", "factor_cov_matrix failed on y", y, ""); @@ -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..ec23cda3492 100644 --- a/stan/math/prim/constraint/cov_matrix_constrain.hpp +++ b/stan/math/prim/constraint/cov_matrix_constrain.hpp @@ -29,7 +29,7 @@ namespace math { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cov_matrix_constrain(const T& x, Eigen::Index K) { +cov_matrix_constrain(T&& x, Eigen::Index K) { using Eigen::Dynamic; using Eigen::Matrix; using std::exp; @@ -37,7 +37,7 @@ cov_matrix_constrain(const T& x, Eigen::Index K) { Matrix, Dynamic, Dynamic> L(K, K); check_size_match("cov_matrix_constrain", "x.size()", x.size(), "K + (K choose 2)", (K * (K + 1)) / 2); - const auto& x_ref = to_ref(x); + auto&& x_ref = to_ref(std::forward(x)); int i = 0; for (Eigen::Index m = 0; m < K; ++m) { L.row(m).head(m) = x_ref.segment(i, m); @@ -45,7 +45,7 @@ cov_matrix_constrain(const T& x, Eigen::Index K) { L.coeffRef(m, m) = exp(x_ref.coeff(i++)); L.row(m).tail(K - m - 1).setZero(); } - return multiply_lower_tri_self_transpose(L); + return multiply_lower_tri_self_transpose(std::move(L)); } /** @@ -65,7 +65,7 @@ cov_matrix_constrain(const T& x, Eigen::Index K) { template * = nullptr, require_convertible_t, Lp>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) { +cov_matrix_constrain(T&& x, Eigen::Index K, Lp& lp) { using Eigen::Dynamic; using Eigen::Matrix; using std::exp; @@ -73,7 +73,7 @@ cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) { check_size_match("cov_matrix_constrain", "x.size()", x.size(), "K + (K choose 2)", (K * (K + 1)) / 2); Matrix, Dynamic, Dynamic> L(K, K); - const auto& x_ref = to_ref(x); + auto&& x_ref = to_ref(std::forward(x)); int i = 0; for (Eigen::Index m = 0; m < K; ++m) { L.row(m).head(m) = x_ref.segment(i, m); @@ -86,7 +86,7 @@ cov_matrix_constrain(const T& x, Eigen::Index K, Lp& lp) { for (Eigen::Index k = 0; k < K; ++k) { lp += (K - k + 1) * log(L.coeff(k, k)); // only +1 because index from 0 } - return multiply_lower_tri_self_transpose(L); + return multiply_lower_tri_self_transpose(std::move(L)); } /** @@ -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..360353180ef 100644 --- a/stan/math/prim/constraint/cov_matrix_free.hpp +++ b/stan/math/prim/constraint/cov_matrix_free.hpp @@ -35,8 +35,8 @@ namespace math { * has zero dimensionality, or has a non-positive diagonal element. */ template * = nullptr> -Eigen::Matrix, Eigen::Dynamic, 1> cov_matrix_free(const T& y) { - const auto& y_ref = to_ref(y); +Eigen::Matrix, Eigen::Dynamic, 1> cov_matrix_free(T&& y) { + auto&& y_ref = to_ref(std::forward(y)); check_square("cov_matrix_free", "y", y_ref); check_nonzero_size("cov_matrix_free", "y", y_ref); @@ -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..fccc40a881a 100644 --- a/stan/math/prim/constraint/cov_matrix_free_lkj.hpp +++ b/stan/math/prim/constraint/cov_matrix_free_lkj.hpp @@ -28,8 +28,7 @@ namespace math { * factorized by factor_cov_matrix() */ template * = nullptr> -Eigen::Matrix, Eigen::Dynamic, 1> cov_matrix_free_lkj( - const T& y) { +Eigen::Matrix, Eigen::Dynamic, 1> cov_matrix_free_lkj(T&& y) { using Eigen::Array; using Eigen::Dynamic; using Eigen::Matrix; @@ -40,8 +39,8 @@ Eigen::Matrix, Eigen::Dynamic, 1> cov_matrix_free_lkj( Eigen::Index k = y.rows(); Eigen::Index k_choose_2 = (k * (k - 1)) / 2; Matrix x(k_choose_2 + k); - bool successful - = factor_cov_matrix(y, x.head(k_choose_2).array(), x.tail(k).array()); + bool successful = factor_cov_matrix( + std::forward(y), x.head(k_choose_2).array(), x.tail(k).array()); if (!successful) { throw_domain_error("cov_matrix_free_lkj", "factor_cov_matrix failed on y", "", ""); @@ -57,9 +56,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..11ce3a52471 100644 --- a/stan/math/prim/constraint/lb_constrain.hpp +++ b/stan/math/prim/constraint/lb_constrain.hpp @@ -34,7 +34,7 @@ namespace math { */ template * = nullptr, require_all_not_st_var* = nullptr> -inline auto lb_constrain(const T& x, const L& lb) { +inline auto lb_constrain(T&& x, const L& lb) { if (unlikely(value_of_rec(lb) == NEGATIVE_INFTY)) { return identity_constrain(x, lb); } else { @@ -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_free.hpp b/stan/math/prim/constraint/lub_free.hpp index 15cb46beb7e..15323e1eac2 100644 --- a/stan/math/prim/constraint/lub_free.hpp +++ b/stan/math/prim/constraint/lub_free.hpp @@ -47,11 +47,11 @@ inline auto lub_free(T&& y, L&& lb, U&& ub) { const bool is_lb_inf = value_of(lb) == NEGATIVE_INFTY; const bool is_ub_inf = value_of(ub) == INFTY; if (unlikely(is_ub_inf && is_lb_inf)) { - return identity_free(y, lb, ub); + return identity_free(std::forward(y), lb, ub); } else if (unlikely(is_ub_inf)) { - return lb_free(identity_free(y, ub), lb); + return lb_free(identity_free(std::forward(y), ub), lb); } else if (unlikely(is_lb_inf)) { - return ub_free(identity_free(y, lb), ub); + return ub_free(identity_free(std::forward(y), lb), ub); } else { auto&& y_ref = to_ref(std::forward(y)); check_bounded("lub_free", "Bounded variable", value_of(y_ref), value_of(lb), diff --git a/stan/math/prim/constraint/offset_multiplier_constrain.hpp b/stan/math/prim/constraint/offset_multiplier_constrain.hpp index 186c8f38988..333b5d00761 100644 --- a/stan/math/prim/constraint/offset_multiplier_constrain.hpp +++ b/stan/math/prim/constraint/offset_multiplier_constrain.hpp @@ -41,25 +41,28 @@ namespace math { */ template * = nullptr> -inline auto offset_multiplier_constrain(const T& x, const M& mu, - const S& sigma) { - const auto& mu_ref = to_ref(mu); - const auto& sigma_ref = to_ref(sigma); + T, M, S>* = nullptr, + require_all_not_std_vector_t* = nullptr> +inline auto offset_multiplier_constrain(T&& x, M&& mu, S&& sigma) { + auto&& mu_ref = to_ref(std::forward(mu)); + auto&& sigma_ref = to_ref(std::forward(sigma)); if (is_matrix::value && is_matrix::value) { - check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); + check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu_ref); } if (is_matrix::value && is_matrix::value) { - check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", sigma); + check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", + sigma_ref); } else if (is_matrix::value && is_matrix::value) { - check_matching_dims("offset_multiplier_constrain", "mu", mu, "sigma", - sigma); + check_matching_dims("offset_multiplier_constrain", "mu", mu_ref, "sigma", + sigma_ref); } check_finite("offset_multiplier_constrain", "offset", value_of_rec(mu_ref)); check_positive_finite("offset_multiplier_constrain", "multiplier", value_of_rec(sigma_ref)); - return stan::math::eval(fma(sigma_ref, x, mu_ref)); + return stan::math::eval(fma(std::forward(sigma_ref), + std::forward(x), + std::forward(mu_ref))); } /** @@ -92,11 +95,11 @@ inline auto offset_multiplier_constrain(const T& x, const M& mu, template , Lp>* = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t< - T, M, S>* = nullptr> -inline auto offset_multiplier_constrain(const T& x, const M& mu, const S& sigma, - Lp& lp) { - const auto& mu_ref = to_ref(mu); - const auto& sigma_ref = to_ref(sigma); + T, M, S>* = nullptr, + require_all_not_std_vector_t* = nullptr> +inline auto offset_multiplier_constrain(T&& x, M&& mu, S&& sigma, Lp& lp) { + auto&& mu_ref = to_ref(std::forward(mu)); + auto&& sigma_ref = to_ref(std::forward(sigma)); if (is_matrix::value && is_matrix::value) { check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); } @@ -115,7 +118,9 @@ inline auto offset_multiplier_constrain(const T& x, const M& mu, const S& sigma, } else { lp += sum(log(sigma_ref)); } - return stan::math::eval(fma(sigma_ref, x, mu_ref)); + return stan::math::eval(fma(std::forward(sigma_ref), + std::forward(x), + std::forward(mu_ref))); } /** @@ -303,12 +308,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/offset_multiplier_free.hpp b/stan/math/prim/constraint/offset_multiplier_free.hpp index 372d5095d23..01a61fc4c9f 100644 --- a/stan/math/prim/constraint/offset_multiplier_free.hpp +++ b/stan/math/prim/constraint/offset_multiplier_free.hpp @@ -39,38 +39,42 @@ namespace math { * @throw std::domain_error if mu is not finite * @throw std::invalid_argument if non-scalar arguments don't match in size */ -template -inline auto offset_multiplier_free(const T& y, const M& mu, const S& sigma) { - auto&& mu_ref = to_ref(mu); - auto&& sigma_ref = to_ref(sigma); - if (is_matrix::value && is_matrix::value) { - check_matching_dims("offset_multiplier_constrain", "y", y, "mu", mu); +template * = nullptr> +inline auto offset_multiplier_free(T&& y, M&& mu, S&& sigma) { + auto&& mu_ref = to_ref(std::forward(mu)); + auto&& sigma_ref = to_ref(std::forward(sigma)); + if constexpr (is_matrix::value && is_matrix::value) { + check_matching_dims("offset_multiplier_constrain", "y", y, "mu", mu_ref); } - if (is_matrix::value && is_matrix::value) { - check_matching_dims("offset_multiplier_constrain", "y", y, "sigma", sigma); - } else if (is_matrix::value && is_matrix::value) { - check_matching_dims("offset_multiplier_constrain", "mu", mu, "sigma", - sigma); + if constexpr (is_matrix::value && is_matrix::value) { + check_matching_dims("offset_multiplier_constrain", "y", y, "sigma", + sigma_ref); + } else if constexpr (is_matrix::value && is_matrix::value) { + check_matching_dims("offset_multiplier_constrain", "mu", mu_ref, "sigma", + sigma_ref); } check_finite("offset_multiplier_constrain", "offset", value_of(mu_ref)); check_positive_finite("offset_multiplier_constrain", "multiplier", value_of(sigma_ref)); - return stan::math::eval(divide(subtract(y, mu_ref), sigma_ref)); + return stan::math::eval(divide( + subtract(std::forward(y), std::forward(mu_ref)), + std::forward(sigma_ref))); } /** * Overload for array of x and non-array mu and sigma */ template * = nullptr, require_all_not_std_vector_t* = nullptr> -inline auto offset_multiplier_free(const std::vector& x, const M& mu, - const S& sigma) { +inline auto offset_multiplier_free(T&& x, M&& mu, S&& sigma) { std::vector> ret; ret.reserve(x.size()); - const auto& mu_ref = to_ref(mu); - const auto& sigma_ref = to_ref(sigma); + auto&& mu_ref = to_ref(std::forward(mu)); + auto&& sigma_ref = to_ref(std::forward(sigma)); for (size_t i = 0; i < x.size(); ++i) { ret.emplace_back(offset_multiplier_free(x[i], mu_ref, sigma_ref)); } @@ -81,15 +85,15 @@ inline auto offset_multiplier_free(const std::vector& x, const M& mu, * Overload for array of x and sigma and non-array mu */ template * = nullptr, require_not_std_vector_t* = nullptr> -inline auto offset_multiplier_free(const std::vector& x, const M& mu, - const std::vector& sigma) { +inline auto offset_multiplier_free(T&& x, M&& mu, S&& sigma) { check_matching_dims("offset_multiplier_free", "x", x, "sigma", sigma); std::vector< plain_type_t> ret; ret.reserve(x.size()); - const auto& mu_ref = to_ref(mu); + auto&& mu_ref = to_ref(std::forward(mu)); for (size_t i = 0; i < x.size(); ++i) { ret.emplace_back(offset_multiplier_free(x[i], mu_ref, sigma[i])); } @@ -100,9 +104,9 @@ inline auto offset_multiplier_free(const std::vector& x, const M& mu, * Overload for array of x and mu and non-array sigma */ template * = nullptr, require_not_std_vector_t* = nullptr> -inline auto offset_multiplier_free(const std::vector& x, - const std::vector& mu, const S& sigma) { +inline auto offset_multiplier_free(T&& x, M&& mu, const S& sigma) { check_matching_dims("offset_multiplier_free", "x", x, "mu", mu); std::vector< plain_type_t> @@ -118,10 +122,9 @@ inline auto offset_multiplier_free(const std::vector& x, /** * Overload for array of x, mu, and sigma */ -template -inline auto offset_multiplier_free(const std::vector& x, - const std::vector& mu, - const std::vector& sigma) { +template * = nullptr> +inline auto offset_multiplier_free(T&& x, M&& mu, S&& sigma) { check_matching_dims("offset_multiplier_free", "x", x, "mu", mu); check_matching_dims("offset_multiplier_free", "x", x, "sigma", sigma); std::vector< diff --git a/stan/math/prim/constraint/ordered_constrain.hpp b/stan/math/prim/constraint/ordered_constrain.hpp index 9fab8f2225d..d88f87630f7 100644 --- a/stan/math/prim/constraint/ordered_constrain.hpp +++ b/stan/math/prim/constraint/ordered_constrain.hpp @@ -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); +inline auto ordered_constrain(EigVec&& x, Lp& lp) { + auto&& x_ref = to_ref(std::forward(x)); if (likely(x.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..dcdec38b7a2 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,9 @@ 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) { +inline auto positive_constrain(T&& x, S& lp) { lp += sum(x); - return exp(x); + return exp(std::forward(x)); } /** @@ -66,11 +66,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 +95,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..55e184c8254 100644 --- a/stan/math/prim/constraint/positive_free.hpp +++ b/stan/math/prim/constraint/positive_free.hpp @@ -26,9 +26,9 @@ namespace math { * @throw std::domain_error if the variable is negative */ template -inline plain_type_t positive_free(const T& y) { +inline plain_type_t positive_free(T&& y) { check_positive("positive_free", "Positive variable", y); - return log(y); + return log(std::forward(y)); } } // namespace math diff --git a/stan/math/prim/constraint/positive_ordered_constrain.hpp b/stan/math/prim/constraint/positive_ordered_constrain.hpp index 4d1f228814f..d0dcdbd1949 100644 --- a/stan/math/prim/constraint/positive_ordered_constrain.hpp +++ b/stan/math/prim/constraint/positive_ordered_constrain.hpp @@ -52,11 +52,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 +70,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 +92,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 +119,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..7bc61dd7a87 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)); } /** @@ -48,10 +48,10 @@ inline T prob_constrain(const T& x) { * @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); +inline auto prob_constrain(T&& x, return_type_t& lp) { + plain_type_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)); } /** @@ -69,11 +69,11 @@ inline T prob_constrain(const T& x, T& lp) { * @return result constrained to fall in (0, 1) */ template -inline auto prob_constrain(const T& x, T& lp) { - if (Jacobian) { - return prob_constrain(x, lp); +inline auto prob_constrain(T&& x, return_type_t& lp) { + if constexpr (Jacobian) { + 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..adb2b5d6c61 100644 --- a/stan/math/prim/constraint/prob_free.hpp +++ b/stan/math/prim/constraint/prob_free.hpp @@ -24,10 +24,10 @@ namespace math { * @throw std::domain_error if y is not in (0, 1) */ template -inline T prob_free(const T& y) { +inline auto prob_free(T&& y) { check_bounded("prob_free", "Probability variable", y, 0, 1); - return logit(y); + return logit(std::forward(y)); } } // 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..e1c7f0c0451 100644 --- a/stan/math/prim/constraint/stochastic_column_constrain.hpp +++ b/stan/math/prim/constraint/stochastic_column_constrain.hpp @@ -21,8 +21,8 @@ namespace math { */ template * = nullptr, require_not_st_var* = nullptr> -inline plain_type_t stochastic_column_constrain(const Mat& y) { - auto&& y_ref = to_ref(y); +inline plain_type_t stochastic_column_constrain(Mat&& y) { + auto&& y_ref = to_ref(std::forward(y)); const Eigen::Index M = y_ref.cols(); plain_type_t ret(y_ref.rows() + 1, M); for (Eigen::Index i = 0; i < M; ++i) { @@ -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..39d17042064 100644 --- a/stan/math/prim/constraint/stochastic_column_free.hpp +++ b/stan/math/prim/constraint/stochastic_column_free.hpp @@ -18,8 +18,8 @@ namespace math { * @param y Columnwise stochastic matrix input of dimensionality (N, K) */ template * = nullptr> -inline plain_type_t stochastic_column_free(const Mat& y) { - auto&& y_ref = to_ref(y); +inline plain_type_t stochastic_column_free(Mat&& y) { + auto&& y_ref = to_ref(std::forward(y)); const Eigen::Index M = y_ref.cols(); plain_type_t ret(y_ref.rows() - 1, M); for (Eigen::Index i = 0; i < M; ++i) { @@ -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..0b34bd25d7c 100644 --- a/stan/math/prim/constraint/stochastic_row_constrain.hpp +++ b/stan/math/prim/constraint/stochastic_row_constrain.hpp @@ -21,8 +21,8 @@ namespace math { */ template * = nullptr, require_not_st_var* = nullptr> -inline plain_type_t stochastic_row_constrain(const Mat& y) { - auto&& y_ref = to_ref(y); +inline plain_type_t stochastic_row_constrain(Mat&& y) { + auto&& y_ref = to_ref(std::forward(y)); const Eigen::Index N = y_ref.rows(); plain_type_t ret(N, y_ref.cols() + 1); for (Eigen::Index i = 0; i < N; ++i) { @@ -47,8 +47,8 @@ template * = nullptr, require_not_st_var* = nullptr, require_convertible_t, Lp>* = nullptr> -inline plain_type_t stochastic_row_constrain(const Mat& y, Lp& lp) { - auto&& y_ref = to_ref(y); +inline plain_type_t stochastic_row_constrain(Mat&& y, Lp& lp) { + auto&& y_ref = to_ref(std::forward(y)); const Eigen::Index N = y_ref.rows(); plain_type_t ret(N, y_ref.cols() + 1); for (Eigen::Index i = 0; i < N; ++i) { @@ -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..9934eeb10e0 100644 --- a/stan/math/prim/constraint/stochastic_row_free.hpp +++ b/stan/math/prim/constraint/stochastic_row_free.hpp @@ -17,8 +17,8 @@ namespace math { * @param y Rowwise simplex Matrix input of dimensionality (N, K) */ template * = nullptr> -inline plain_type_t stochastic_row_free(const Mat& y) { - auto&& y_ref = to_ref(y); +inline plain_type_t stochastic_row_free(Mat&& y) { + auto&& y_ref = to_ref(std::forward(y)); const Eigen::Index N = y_ref.rows(); plain_type_t ret(N, y_ref.cols() - 1); for (Eigen::Index i = 0; i < N; ++i) { @@ -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..2bd72669599 100644 --- a/stan/math/prim/constraint/sum_to_zero_constrain.hpp +++ b/stan/math/prim/constraint/sum_to_zero_constrain.hpp @@ -122,9 +122,9 @@ inline plain_type_t sum_to_zero_constrain(const Mat& x) { * @param lp unused * @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); +template * = nullptr> +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), [&lp](auto&& v) { + return sum_to_zero_constrain(std::forward(v), lp); + }); } /** @@ -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), lp); } } // 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..bef8aee2324 100644 --- a/stan/math/prim/constraint/ub_constrain.hpp +++ b/stan/math/prim/constraint/ub_constrain.hpp @@ -88,8 +88,9 @@ inline auto ub_constrain(const T& x, const U& ub, Lp& lp) { template * = nullptr, require_stan_scalar_t* = nullptr, require_all_not_st_var* = nullptr> -inline auto ub_constrain(const T& x, const U& ub) { - return eval(x.unaryExpr([ub](auto&& xx) { return ub_constrain(xx, ub); })); +inline auto ub_constrain(T&& x, const U& ub) { + return eval(std::forward(x).unaryExpr( + [ub](auto&& xx) { return ub_constrain(xx, ub); })); } /** @@ -108,9 +109,9 @@ template * = nullptr, require_stan_scalar_t* = nullptr, require_all_not_st_var* = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto ub_constrain(const T& x, const U& ub, Lp& lp) { - return eval( - x.unaryExpr([ub, &lp](auto&& xx) { return ub_constrain(xx, ub, lp); })); +inline auto ub_constrain(T&& x, const U& ub, Lp& lp) { + return eval(std::forward(x).unaryExpr( + [ub, &lp](auto&& xx) { return ub_constrain(xx, ub, lp); })); } /** @@ -125,9 +126,9 @@ inline auto ub_constrain(const T& x, const U& ub, Lp& lp) { */ template * = nullptr, require_all_not_st_var* = nullptr> -inline auto ub_constrain(const T& x, const U& ub) { +inline auto ub_constrain(T&& x, const U& ub) { check_matching_dims("ub_constrain", "x", x, "ub", ub); - return eval(x.binaryExpr( + return eval(std::forward(x).binaryExpr( ub, [](auto&& xx, auto&& ubb) { return ub_constrain(xx, ubb); })); } @@ -147,9 +148,9 @@ template * = nullptr, require_all_not_st_var* = nullptr, require_convertible_t, Lp>* = nullptr> -inline auto ub_constrain(const T& x, const U& ub, Lp& lp) { +inline auto ub_constrain(T&& x, const U& ub, Lp& lp) { check_matching_dims("ub_constrain", "x", x, "ub", ub); - return eval(x.binaryExpr( + return eval(std::forward(x).binaryExpr( ub, [&lp](auto&& xx, auto&& ubb) { return ub_constrain(xx, ubb, lp); })); } @@ -261,11 +262,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/ub_free.hpp b/stan/math/prim/constraint/ub_free.hpp index 05a3acce775..415fe38ff5d 100644 --- a/stan/math/prim/constraint/ub_free.hpp +++ b/stan/math/prim/constraint/ub_free.hpp @@ -34,7 +34,7 @@ template * = nullptr, require_stan_scalar_t* = nullptr> inline auto ub_free(T&& y, U&& ub) { if (value_of_rec(ub) == INFTY) { - return identity_free(y, ub); + return identity_free(std::forward(y), std::forward(ub)); } else { auto&& y_ref = to_ref(std::forward(y)); auto&& ub_ref = to_ref(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..3fcdd598166 100644 --- a/stan/math/prim/constraint/unit_vector_constrain.hpp +++ b/stan/math/prim/constraint/unit_vector_constrain.hpp @@ -24,13 +24,17 @@ namespace math { */ template * = nullptr, require_not_vt_autodiff* = nullptr> -inline plain_type_t unit_vector_constrain(const T& y) { +inline auto unit_vector_constrain(T&& y) { using std::sqrt; check_nonzero_size("unit_vector_constrain", "y", y); - auto&& y_ref = to_ref(y); + auto&& y_ref = to_ref(std::forward(y)); value_type_t SN = dot_self(y_ref); check_positive_finite("unit_vector_constrain", "norm", SN); - return y_ref.array() / sqrt(SN); + return make_holder( + [SN](auto&& y_) { + return std::forward(y_).array() / sqrt(SN); + }, + std::forward(y_ref)); } /** @@ -46,14 +50,18 @@ inline plain_type_t unit_vector_constrain(const T& y) { */ template * = nullptr, require_all_not_vt_autodiff* = nullptr> -inline plain_type_t unit_vector_constrain(const T1& y, T2& lp) { +inline auto unit_vector_constrain(T1&& y, T2& lp) { using std::sqrt; check_nonzero_size("unit_vector_constrain", "y", y); auto&& y_ref = to_ref(y); value_type_t SN = dot_self(y_ref); check_positive_finite("unit_vector_constrain", "norm", SN); lp -= 0.5 * SN; - return y_ref.array() / sqrt(SN); + return make_holder( + [SN](auto&& y_) { + return std::forward(y_).array() / sqrt(SN); + }, + std::forward(y_ref)); } /** * Return the unit length vector corresponding to the free vector y. @@ -66,9 +74,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 +95,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 +121,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..01624e01a4e 100644 --- a/stan/math/prim/constraint/unit_vector_free.hpp +++ b/stan/math/prim/constraint/unit_vector_free.hpp @@ -25,7 +25,7 @@ inline auto unit_vector_free(EigVec&& x) { auto&& x_ref = to_ref(std::forward(x)); check_unit_vector("stan::math::unit_vector_free", "Unit vector variable", x_ref); - return x_ref; + return std::forward(x_ref); } /** @@ -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/err/is_symmetric.hpp b/stan/math/prim/err/is_symmetric.hpp index ccd16b37b06..46a7345ad0b 100644 --- a/stan/math/prim/err/is_symmetric.hpp +++ b/stan/math/prim/err/is_symmetric.hpp @@ -21,8 +21,8 @@ namespace math { * element not on the main diagonal is NaN */ template * = nullptr> -inline bool is_symmetric(const EigMat& y) { - const auto& y_ref = to_ref(y); +inline bool is_symmetric(EigMat&& y) { + auto&& y_ref = to_ref(std::forward(y)); if (!is_square(y_ref)) { return false; } diff --git a/stan/math/prim/fun/Phi.hpp b/stan/math/prim/fun/Phi.hpp index 152ab151bcf..ea2de28f896 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_not_var_matrix_t* = nullptr, require_container_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..5dd82dd85a9 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_not_var_matrix_t* = nullptr, require_container_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..9d91fd19f4c 100644 --- a/stan/math/prim/fun/abs.hpp +++ b/stan/math/prim/fun/abs.hpp @@ -49,8 +49,8 @@ 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) { + return abs(std::forward(x)); } }; @@ -63,8 +63,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 +78,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), + [&](auto&& v) { return std::forward(v).array().abs(); }); } namespace internal { diff --git a/stan/math/prim/fun/acos.hpp b/stan/math/prim/fun/acos.hpp index 1efa76b5174..57644a690e2 100644 --- a/stan/math/prim/fun/acos.hpp +++ b/stan/math/prim/fun/acos.hpp @@ -51,8 +51,8 @@ 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) { + return acos(std::forward(x)); } }; @@ -65,8 +65,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 +80,10 @@ 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 std::forward(v).array().acos(); }); } namespace internal { diff --git a/stan/math/prim/fun/acosh.hpp b/stan/math/prim/fun/acosh.hpp index 5580e9e1e73..28a10719326 100644 --- a/stan/math/prim/fun/acosh.hpp +++ b/stan/math/prim/fun/acosh.hpp @@ -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/add.hpp b/stan/math/prim/fun/add.hpp index 763c51da1e9..4433baca56d 100644 --- a/stan/math/prim/fun/add.hpp +++ b/stan/math/prim/fun/add.hpp @@ -40,9 +40,14 @@ inline return_type_t add(const ScalarA& a, const ScalarB& b) { template * = nullptr, require_all_not_st_var* = nullptr> -inline auto add(const Mat1& m1, const Mat2& m2) { +inline auto add(Mat1&& m1, Mat2&& m2) { check_matching_dims("add", "m1", m1, "m2", m2); - return m1 + m2; + return make_holder( + [](auto&& m1_, auto&& m2_) { + return std::forward(m1_) + + std::forward(m2_); + }, + std::forward(m1), std::forward(m2)); } /** @@ -57,8 +62,12 @@ inline auto add(const Mat1& m1, const Mat2& m2) { template * = nullptr, require_stan_scalar_t* = nullptr, require_all_not_st_var* = nullptr> -inline auto add(const Mat& m, const Scal c) { - return (m.array() + c).matrix(); +inline auto add(Mat&& m, const Scal c) { + return make_holder( + [c](auto&& m_) { + return (std::forward(m_).array() + c).matrix(); + }, + std::forward(m)); } /** @@ -73,8 +82,12 @@ inline auto add(const Mat& m, const Scal c) { template * = nullptr, require_eigen_t* = nullptr, require_all_not_st_var* = nullptr> -inline auto add(const Scal c, const Mat& m) { - return (c + m.array()).matrix(); +inline auto add(const Scal c, Mat&& m) { + return make_holder( + [c](auto&& m_) { + return (c + std::forward(m_).array()).matrix(); + }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/asin.hpp b/stan/math/prim/fun/asin.hpp index f620a24d2af..fd06356cb0f 100644 --- a/stan/math/prim/fun/asin.hpp +++ b/stan/math/prim/fun/asin.hpp @@ -49,8 +49,8 @@ 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) { + return asin(std::forward(x)); } }; @@ -63,8 +63,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 +78,10 @@ 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 std::forward(v).array().asin(); }); } namespace internal { diff --git a/stan/math/prim/fun/asinh.hpp b/stan/math/prim/fun/asinh.hpp index ab72065efae..32089403e8b 100644 --- a/stan/math/prim/fun/asinh.hpp +++ b/stan/math/prim/fun/asinh.hpp @@ -52,8 +52,8 @@ 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) { + return asinh(std::forward(x)); } }; @@ -66,8 +66,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 +80,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..497a024d39e 100644 --- a/stan/math/prim/fun/atan.hpp +++ b/stan/math/prim/fun/atan.hpp @@ -47,8 +47,8 @@ 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) { + return atan(std::forward(x)); } }; @@ -61,8 +61,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 +76,10 @@ 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 std::forward(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..616a381ba72 100644 --- a/stan/math/prim/fun/atanh.hpp +++ b/stan/math/prim/fun/atanh.hpp @@ -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/block.hpp b/stan/math/prim/fun/block.hpp index 7f5b2aaa850..936de76522f 100644 --- a/stan/math/prim/fun/block.hpp +++ b/stan/math/prim/fun/block.hpp @@ -19,12 +19,16 @@ namespace math { * @throw std::out_of_range if either index is out of range. */ template * = nullptr> -inline auto block(const T& m, size_t i, size_t j, size_t nrows, size_t ncols) { +inline auto block(T&& m, size_t i, size_t j, size_t nrows, size_t ncols) { check_row_index("block", "i", m, i); check_row_index("block", "i+nrows-1", m, i + nrows - 1); check_column_index("block", "j", m, j); check_column_index("block", "j+ncols-1", m, j + ncols - 1); - return m.block(i - 1, j - 1, nrows, ncols); + return make_holder( + [i, j, nrows, ncols](auto&& m_) { + return std::forward(m_).block(i - 1, j - 1, nrows, ncols); + }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/cbrt.hpp b/stan/math/prim/fun/cbrt.hpp index 090105f25aa..22f71fd934d 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(std::forward(x)); +} + /** * Structure to wrap `cbrt()` so it can be vectorized. * @@ -17,9 +22,8 @@ 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) { + return cbrt(std::forward(x)); } }; @@ -33,9 +37,10 @@ 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) { - return apply_scalar_unary::apply(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(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/ceil.hpp b/stan/math/prim/fun/ceil.hpp index c257837250e..612ad29fd1e 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,8 @@ 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) { + return ceil(std::forward(x)); } }; @@ -36,9 +40,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 +58,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), + [](auto&& v) { return std::forward(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/cols.hpp b/stan/math/prim/fun/cols.hpp index 07a24d5867a..c1069a723b9 100644 --- a/stan/math/prim/fun/cols.hpp +++ b/stan/math/prim/fun/cols.hpp @@ -17,8 +17,8 @@ namespace math { * @return Number of columns. */ template * = nullptr> -inline int64_t cols(const T& m) { - return m.cols(); +inline Eigen::Index cols(T&& m) { + return make_holder([](auto&& arg) { return arg.cols(); }, std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/columns_dot_product.hpp b/stan/math/prim/fun/columns_dot_product.hpp index 2dcb69e2d17..8449e194598 100644 --- a/stan/math/prim/fun/columns_dot_product.hpp +++ b/stan/math/prim/fun/columns_dot_product.hpp @@ -24,10 +24,16 @@ namespace math { template * = nullptr, require_all_not_eigen_vt* = nullptr> -inline Eigen::Matrix, 1, Mat1::ColsAtCompileTime> -columns_dot_product(const Mat1& v1, const Mat2& v2) { +inline auto columns_dot_product(Mat1&& v1, Mat2&& v2) { check_matching_dims("columns_dot_product", "v1", v1, "v2", v2); - return v1.cwiseProduct(v2).colwise().sum(); + return make_holder( + [](auto&& v1_, auto&& v2_) { + return std::forward(v1_) + .cwiseProduct(std::forward(v2_)) + .colwise() + .sum(); + }, + std::forward(v1), std::forward(v2)); } } // namespace math diff --git a/stan/math/prim/fun/columns_dot_self.hpp b/stan/math/prim/fun/columns_dot_self.hpp index 3baa49047f1..941d84a92c5 100644 --- a/stan/math/prim/fun/columns_dot_self.hpp +++ b/stan/math/prim/fun/columns_dot_self.hpp @@ -18,9 +18,12 @@ namespace math { */ template * = nullptr, require_not_eigen_vt* = nullptr> -inline Eigen::Matrix, 1, T::ColsAtCompileTime> columns_dot_self( - const T& x) { - return x.colwise().squaredNorm(); +inline auto columns_dot_self(T&& x) { + return make_holder( + [](auto&& x_) { + return std::forward(x_).colwise().squaredNorm(); + }, + std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/cos.hpp b/stan/math/prim/fun/cos.hpp index 0a3b044ccdc..e7067f6d092 100644 --- a/stan/math/prim/fun/cos.hpp +++ b/stan/math/prim/fun/cos.hpp @@ -46,8 +46,8 @@ 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) { + return cos(std::forward(x)); } }; @@ -60,8 +60,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 +75,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), + [&](auto&& v) { return std::forward(v).array().cos(); }); } namespace internal { diff --git a/stan/math/prim/fun/cosh.hpp b/stan/math/prim/fun/cosh.hpp index ae60c233a68..59f305adb65 100644 --- a/stan/math/prim/fun/cosh.hpp +++ b/stan/math/prim/fun/cosh.hpp @@ -45,8 +45,8 @@ 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) { + return cosh(std::forward(x)); } }; @@ -59,8 +59,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 +74,10 @@ 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 std::forward(v).array().cosh(); }); } namespace internal { diff --git a/stan/math/prim/fun/crossprod.hpp b/stan/math/prim/fun/crossprod.hpp index d9e868aceed..d83ea697d8b 100644 --- a/stan/math/prim/fun/crossprod.hpp +++ b/stan/math/prim/fun/crossprod.hpp @@ -17,8 +17,8 @@ namespace math { * @return Transpose of M times M */ template * = nullptr> -inline auto crossprod(const EigMat& M) { - return tcrossprod(M.transpose()); +inline auto crossprod(EigMat&& M) { + return tcrossprod(std::forward(M).transpose()); } } // namespace math diff --git a/stan/math/prim/fun/determinant.hpp b/stan/math/prim/fun/determinant.hpp index fb26b80e2a5..851ce460c92 100644 --- a/stan/math/prim/fun/determinant.hpp +++ b/stan/math/prim/fun/determinant.hpp @@ -18,9 +18,10 @@ namespace math { * @throw std::domain_error if matrix is not square. */ template * = nullptr> -inline value_type_t determinant(const T& m) { +inline value_type_t determinant(T&& m) { check_square("determinant", "m", m); - return m.determinant(); + return make_holder([](auto&& m_) { return m_.determinant(); }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/diag_matrix.hpp b/stan/math/prim/fun/diag_matrix.hpp index 89b978e655e..47902f9e2d8 100644 --- a/stan/math/prim/fun/diag_matrix.hpp +++ b/stan/math/prim/fun/diag_matrix.hpp @@ -18,8 +18,9 @@ namespace math { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -diag_matrix(const EigVec& v) { - return v.asDiagonal(); +diag_matrix(EigVec&& v) { + return make_holder([](auto&& v_) { return v_.asDiagonal(); }, + std::forward(v)); } } // namespace math diff --git a/stan/math/prim/fun/diag_post_multiply.hpp b/stan/math/prim/fun/diag_post_multiply.hpp index 5564618660d..34c879e3920 100644 --- a/stan/math/prim/fun/diag_post_multiply.hpp +++ b/stan/math/prim/fun/diag_post_multiply.hpp @@ -22,10 +22,15 @@ namespace math { template * = nullptr, require_eigen_vector_t* = nullptr, require_all_not_st_var* = nullptr> -auto diag_post_multiply(const T1& m1, const T2& m2) { +auto diag_post_multiply(T1&& m1, T2&& m2) { check_size_match("diag_post_multiply", "m2.size()", m2.size(), "m1.cols()", m1.cols()); - return m1 * m2.asDiagonal(); + return make_holder( + [](auto&& m1_, auto&& m2_) { + return std::forward(m1_) + * std::forward(m2_).asDiagonal(); + }, + std::forward(m1), std::forward(m2)); } } // namespace math diff --git a/stan/math/prim/fun/diag_pre_multiply.hpp b/stan/math/prim/fun/diag_pre_multiply.hpp index a3ed197b6e2..13dec0e71a7 100644 --- a/stan/math/prim/fun/diag_pre_multiply.hpp +++ b/stan/math/prim/fun/diag_pre_multiply.hpp @@ -22,11 +22,15 @@ namespace math { template * = nullptr, require_eigen_t* = nullptr, require_all_not_st_var* = nullptr> -auto diag_pre_multiply(const T1& m1, const T2& m2) { +auto diag_pre_multiply(T1&& m1, T2&& m2) { check_size_match("diag_pre_multiply", "m1.size()", m1.size(), "m2.rows()", m2.rows()); - - return m1.asDiagonal() * m2; + return make_holder( + [](auto&& m1_, auto&& m2_) { + return std::forward(m1_).asDiagonal() + * std::forward(m2_); + }, + std::forward(m1), std::forward(m2)); } } // namespace math diff --git a/stan/math/prim/fun/diagonal.hpp b/stan/math/prim/fun/diagonal.hpp index 49be724814b..7e22d87ad43 100644 --- a/stan/math/prim/fun/diagonal.hpp +++ b/stan/math/prim/fun/diagonal.hpp @@ -16,8 +16,10 @@ namespace math { * @return Diagonal of the matrix. */ template * = nullptr> -inline auto diagonal(const T& m) { - return m.diagonal(); +inline auto diagonal(T&& m) { + return make_holder( + [](auto&& m_) { return std::forward(m_).diagonal(); }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/digamma.hpp b/stan/math/prim/fun/digamma.hpp index 05032782e8c..fd69bcda98f 100644 --- a/stan/math/prim/fun/digamma.hpp +++ b/stan/math/prim/fun/digamma.hpp @@ -58,8 +58,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 +73,9 @@ struct digamma_fun { */ template * = nullptr, - require_not_var_matrix_t* = nullptr> -inline auto digamma(const T& x) { - return apply_scalar_unary::apply(x); + require_container_t* = nullptr> +inline auto digamma(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/distance.hpp b/stan/math/prim/fun/distance.hpp index c46e9eed6c4..ec9552a4f49 100644 --- a/stan/math/prim/fun/distance.hpp +++ b/stan/math/prim/fun/distance.hpp @@ -44,10 +44,10 @@ inline return_type_t distance(const T1& x1, const T2& x2) { * size. */ template * = nullptr> -inline return_type_t distance(const T1& x1, const T2& x2) { +inline return_type_t distance(T1&& x1, T2&& x2) { using std::sqrt; check_matching_sizes("distance", "x1", x1, "x2", x2); - return sqrt(squared_distance(x1, x2)); + return sqrt(squared_distance(std::forward(x1), std::forward(x2))); } } // namespace math diff --git a/stan/math/prim/fun/divide.hpp b/stan/math/prim/fun/divide.hpp index c15ed453953..84b5d35a4bb 100644 --- a/stan/math/prim/fun/divide.hpp +++ b/stan/math/prim/fun/divide.hpp @@ -43,8 +43,14 @@ inline int divide(int x, int y) { */ template * = nullptr, require_all_not_st_var* = nullptr> -inline auto divide(const T1& m, const T2& c) { - return (as_array_or_scalar(m) / as_array_or_scalar(c)).matrix(); +inline auto divide(T1&& m, T2&& c) { + return make_holder( + [](auto&& m_, auto&& c_) { + return (as_array_or_scalar(std::forward(m_)) + / as_array_or_scalar(std::forward(c_))) + .matrix(); + }, + std::forward(m), std::forward(c)); } } // namespace math diff --git a/stan/math/prim/fun/dot_product.hpp b/stan/math/prim/fun/dot_product.hpp index 1a45c854791..d5c879a3194 100644 --- a/stan/math/prim/fun/dot_product.hpp +++ b/stan/math/prim/fun/dot_product.hpp @@ -21,9 +21,10 @@ namespace math { template * = nullptr, require_not_var_t> * = nullptr> -inline auto dot_product(const Vec1 &v1, const Vec2 &v2) { +inline auto dot_product(Vec1 &&v1, Vec2 &&v2) { check_matching_sizes("dot_product", "v1", v1, "v2", v2); - return v1.dot(v2); + return make_holder([](auto &&v1_, auto &&v2_) { return v1_.dot(v2_); }, + std::forward(v1), std::forward(v2)); } /** diff --git a/stan/math/prim/fun/dot_self.hpp b/stan/math/prim/fun/dot_self.hpp index c9d67f56e86..7ec1c77f227 100644 --- a/stan/math/prim/fun/dot_self.hpp +++ b/stan/math/prim/fun/dot_self.hpp @@ -32,8 +32,9 @@ inline double dot_self(const std::vector& x) { */ template * = nullptr, require_not_eigen_vt* = nullptr> -inline value_type_t dot_self(const T& v) { - return v.squaredNorm(); +inline auto dot_self(T&& v) { + return make_holder([](auto&& v_) { return v_.squaredNorm(); }, + std::forward(v)); } } // namespace math diff --git a/stan/math/prim/fun/elt_divide.hpp b/stan/math/prim/fun/elt_divide.hpp index d0fedb64bdc..14d192d8c82 100644 --- a/stan/math/prim/fun/elt_divide.hpp +++ b/stan/math/prim/fun/elt_divide.hpp @@ -22,9 +22,15 @@ namespace math { template * = nullptr, require_all_not_st_var* = nullptr> -auto elt_divide(const Mat1& m1, const Mat2& m2) { +inline auto elt_divide(Mat1&& m1, Mat2&& m2) { check_matching_dims("elt_divide", "m1", m1, "m2", m2); - return (m1.array() / m2.array()).matrix(); + return make_holder( + [](auto&& m1_, auto&& m2_) { + return (std::forward(m1_).array() + / std::forward(m2_).array()) + .matrix(); + }, + std::forward(m1), std::forward(m2)); } /** @@ -40,8 +46,8 @@ auto elt_divide(const Mat1& m1, const Mat2& m2) { */ template * = nullptr, require_stan_scalar_t* = nullptr> -auto elt_divide(const Mat& m, Scal s) { - return divide(m, s); +inline auto elt_divide(Mat&& m, Scal s) { + return divide(std::forward(m), s); } /** @@ -57,8 +63,12 @@ auto elt_divide(const Mat& m, Scal s) { */ template * = nullptr, require_eigen_t* = nullptr> -auto elt_divide(Scal s, const Mat& m) { - return (s / m.array()).matrix(); +auto elt_divide(Scal s, Mat&& m) { + return make_holder( + [s](auto&& m_) { + return (s / std::forward(m_).array()).matrix(); + }, + std::forward(m)); } template * = nullptr, require_all_not_st_var* = nullptr> -auto elt_multiply(const Mat1& m1, const Mat2& m2) { +auto elt_multiply(Mat1&& m1, Mat2&& m2) { check_matching_dims("elt_multiply", "m1", m1, "m2", m2); - return m1.cwiseProduct(m2); + return make_holder( + [](auto&& m1_, auto&& m2_) { + return std::forward(m1_).cwiseProduct( + std::forward(m2_)); + }, + std::forward(m1), std::forward(m2)); } /** @@ -59,8 +64,8 @@ auto elt_multiply(const Scalar1& a, const Scalar2& b) { */ template * = nullptr, require_any_stan_scalar_t* = nullptr> -inline auto elt_multiply(const T1& A, const T2& B) { - return multiply(A, B); +inline auto elt_multiply(T1&& A, T2&& B) { + return multiply(std::forward(A), std::forward(B)); } } // namespace math diff --git a/stan/math/prim/fun/erf.hpp b/stan/math/prim/fun/erf.hpp index 9f3526bcafa..e0e40a93cd7 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(std::forward(x)); +} + /** * Structure to wrap `erf()` so it can be vectorized. * @@ -17,9 +22,8 @@ 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) { + return erf(std::forward(x)); } }; @@ -34,9 +38,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..fdc2f419bb4 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,8 @@ 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) { + return erfc(std::forward(x)); } }; @@ -35,9 +39,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_not_var_matrix_t* = nullptr, require_container_t* = nullptr> +inline auto erfc(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/eval.hpp b/stan/math/prim/fun/eval.hpp index cc7f6718daf..1b2bd48f633 100644 --- a/stan/math/prim/fun/eval.hpp +++ b/stan/math/prim/fun/eval.hpp @@ -31,8 +31,8 @@ inline T eval(T&& arg) { **/ template , plain_type_t>* = nullptr> -inline decltype(auto) eval(const T& arg) { - return arg.eval(); +inline auto eval(T&& arg) { + return plain_type_t(std::forward(arg)); } } // namespace math diff --git a/stan/math/prim/fun/exp.hpp b/stan/math/prim/fun/exp.hpp index d12d82cb556..e3fe876d7e5 100644 --- a/stan/math/prim/fun/exp.hpp +++ b/stan/math/prim/fun/exp.hpp @@ -53,8 +53,8 @@ struct exp_fun { * @return Exponential of argument. */ template - static inline auto fun(const T& x) { - return exp(x); + static inline auto fun(T&& x) { + return exp(std::forward(x)); } }; @@ -68,8 +68,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 +83,10 @@ 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 std::forward(v).array().exp(); }); } namespace internal { diff --git a/stan/math/prim/fun/exp2.hpp b/stan/math/prim/fun/exp2.hpp index f5f491cb926..ee61b7dc684 100644 --- a/stan/math/prim/fun/exp2.hpp +++ b/stan/math/prim/fun/exp2.hpp @@ -8,6 +8,11 @@ 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,8 +25,7 @@ struct exp2_fun { * @return Base two exponent of the argument. */ template - static inline auto fun(const T& x) { - using std::exp2; + static inline auto fun(T&& x) { return exp2(x); } }; @@ -38,9 +42,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_not_var_matrix_t* = nullptr, require_container_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..da367400991 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,8 @@ 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) { + return expm1(std::forward(x)); } }; @@ -35,9 +39,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..b41fece9fa3 100644 --- a/stan/math/prim/fun/fabs.hpp +++ b/stan/math/prim/fun/fabs.hpp @@ -29,8 +29,8 @@ 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) { + return fabs(std::forward(x)); } }; @@ -48,8 +48,9 @@ template * = nullptr, require_not_stan_scalar_t* = nullptr> -inline auto fabs(const Container& x) { - return apply_scalar_unary::apply(x); +inline auto fabs(Container&& x) { + return apply_scalar_unary::apply( + std::forward(x)); } /** @@ -62,9 +63,10 @@ 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 std::forward(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/fft.hpp b/stan/math/prim/fun/fft.hpp index 6610a3dd858..6ba250b5180 100644 --- a/stan/math/prim/fun/fft.hpp +++ b/stan/math/prim/fun/fft.hpp @@ -32,9 +32,9 @@ namespace math { */ template * = nullptr, require_not_var_t>>* = nullptr> -inline Eigen::Matrix, -1, 1> fft(const V& x) { +inline Eigen::Matrix, -1, 1> fft(V&& x) { // copy because fft() requires Eigen::Matrix type - Eigen::Matrix, -1, 1> xv = x; + Eigen::Matrix, -1, 1> xv = std::forward(x); if (xv.size() <= 1) return xv; Eigen::FFT> fft; @@ -63,9 +63,9 @@ inline Eigen::Matrix, -1, 1> fft(const V& x) { */ template * = nullptr, require_not_var_t>>* = nullptr> -inline Eigen::Matrix, -1, 1> inv_fft(const V& y) { +inline Eigen::Matrix, -1, 1> inv_fft(V&& y) { // copy because fft() requires Eigen::Matrix type - Eigen::Matrix, -1, 1> yv = y; + Eigen::Matrix, -1, 1> yv = std::forward(y); if (y.size() <= 1) return yv; Eigen::FFT> fft; diff --git a/stan/math/prim/fun/floor.hpp b/stan/math/prim/fun/floor.hpp index 3845bee34b2..3ca7398986d 100644 --- a/stan/math/prim/fun/floor.hpp +++ b/stan/math/prim/fun/floor.hpp @@ -28,8 +28,8 @@ 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) { + return floor(std::forward(x)); } }; @@ -42,8 +42,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 +58,10 @@ 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 std::forward(v).array().floor(); }); } } // namespace math diff --git a/stan/math/prim/fun/fma.hpp b/stan/math/prim/fun/fma.hpp index 428dff3d810..2cc8cd7dbc2 100644 --- a/stan/math/prim/fun/fma.hpp +++ b/stan/math/prim/fun/fma.hpp @@ -24,8 +24,7 @@ namespace math { template * = nullptr> inline double fma(T1 x, T2 y, T3 z) { - using std::fma; - return fma(x, y, z); + return std::fma(x, y, z); } 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..ef6ac3f6de4 100644 --- a/stan/math/prim/fun/fmin.hpp +++ b/stan/math/prim/fun/fmin.hpp @@ -18,8 +18,7 @@ namespace math { */ template * = nullptr> inline double fmin(T1 x, T2 y) { - using std::fmin; - return fmin(x, y); + return std::fmin(x, y); } /** @@ -33,9 +32,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..b3cc51bb65d 100644 --- a/stan/math/prim/fun/fmod.hpp +++ b/stan/math/prim/fun/fmod.hpp @@ -34,13 +34,13 @@ 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) { + [](auto&& c, auto&& d) { using std::fmod; - return fmod(c, 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..7e598ea2da2 100644 --- a/stan/math/prim/fun/hypot.hpp +++ b/stan/math/prim/fun/hypot.hpp @@ -22,8 +22,7 @@ namespace math { */ template * = nullptr> inline double hypot(T1 x, T2 y) { - using std::hypot; - return hypot(x, y); + return std::hypot(x, y); } /** @@ -39,9 +38,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/inv.hpp b/stan/math/prim/fun/inv.hpp index fe09a75e6df..016e884fd7e 100644 --- a/stan/math/prim/fun/inv.hpp +++ b/stan/math/prim/fun/inv.hpp @@ -9,6 +9,8 @@ namespace stan { namespace math { +inline double inv(double x) { return 1.0 / x; } + /** * Structure to wrap 1.0 / x so that it can be vectorized. * @@ -18,8 +20,8 @@ namespace math { */ struct inv_fun { template - static inline auto fun(const T& x) { - return 1.0 / x; + static inline auto fun(T&& x) { + return inv(std::forward(x)); } }; @@ -33,9 +35,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 +53,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), + [](auto&& v) { return std::forward(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..ed6f12e2c19 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_not_var_matrix_t* = nullptr, require_container_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..e021472a417 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,11 @@ 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), [](const auto& v) { + return (1 - (-std::forward(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..2893534b275 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)); } }; @@ -47,9 +47,9 @@ template < typename T, require_all_not_nonscalar_prim_or_rev_kernel_expression_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); + require_not_arithmetic_t* = nullptr, require_container_t* = nullptr> +inline auto inv_erfc(T&& x) { + return apply_scalar_unary::apply(std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/inv_logit.hpp b/stan/math/prim/fun/inv_logit.hpp index 08f2a940a7f..1db746d7f8a 100644 --- a/stan/math/prim/fun/inv_logit.hpp +++ b/stan/math/prim/fun/inv_logit.hpp @@ -106,7 +106,7 @@ template ::apply( std::forward(x), - [](const auto& v) { return v.array().logistic(); }); + [](auto&& v) { return std::forward(v).array().logistic(); }); } } // namespace math } // namespace stan diff --git a/stan/math/prim/fun/inv_sqrt.hpp b/stan/math/prim/fun/inv_sqrt.hpp index 00fa616a45f..d57fb76b367 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(); }); + return apply_vector_unary >::apply( + std::forward(x), + [](auto&& v) { return std::forward(v).array().rsqrt(); }); #endif } diff --git a/stan/math/prim/fun/inv_square.hpp b/stan/math/prim/fun/inv_square.hpp index 0793e054c3d..e3664f0e75b 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 1.0 / std::pow(x, 2); +} + /** * 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_not_stan_scalar_t* = nullptr> +inline auto inv_square(Container&& x) { + return inv(square(std::forward(x))); } /** @@ -34,9 +40,11 @@ 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 std::forward(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..f634bbd8304 100644 --- a/stan/math/prim/fun/ldexp.hpp +++ b/stan/math/prim/fun/ldexp.hpp @@ -19,8 +19,7 @@ namespace math { */ template * = nullptr> inline double ldexp(T1 a, int b) { - using std::ldexp; - return ldexp(a, b); + return std::ldexp(a, b); } /** @@ -36,9 +35,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..99e36c84025 100644 --- a/stan/math/prim/fun/log.hpp +++ b/stan/math/prim/fun/log.hpp @@ -52,8 +52,8 @@ 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) { + return log(std::forward(x)); } }; @@ -67,8 +67,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 +82,10 @@ 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 std::forward(v).array().log(); }); } namespace internal { diff --git a/stan/math/prim/fun/log10.hpp b/stan/math/prim/fun/log10.hpp index f7d81343ea5..7e827137247 100644 --- a/stan/math/prim/fun/log10.hpp +++ b/stan/math/prim/fun/log10.hpp @@ -45,8 +45,8 @@ 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) { + return log10(std::forward(x)); } }; @@ -58,8 +58,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 +73,10 @@ 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 std::forward(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..69d9d1156c7 100644 --- a/stan/math/prim/fun/log1m_exp.hpp +++ b/stan/math/prim/fun/log1m_exp.hpp @@ -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..f2d11ff0c0b 100644 --- a/stan/math/prim/fun/log1m_inv_logit.hpp +++ b/stan/math/prim/fun/log1m_inv_logit.hpp @@ -65,8 +65,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 +81,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..be59b8d2958 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_not_var_matrix_t* = nullptr> -inline auto log1p(const T& x) { - return apply_scalar_unary::apply(x); + require_not_var_matrix_t* = nullptr, + require_container_t* = nullptr> +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..38c80bf4581 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_not_var_matrix_t* = nullptr> -inline auto log1p_exp(const T& x) { - return apply_scalar_unary::apply(x); + require_not_var_matrix_t* = nullptr, + require_container_t* = nullptr> +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..60bc0fc13ec 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..61ada1bb62c 100644 --- a/stan/math/prim/fun/log_softmax.hpp +++ b/stan/math/prim/fun/log_softmax.hpp @@ -41,14 +41,16 @@ 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) { - return apply_vector_unary>::apply( - a, [](const auto& v) { return v.array() - log_sum_exp(v); }); + [](auto&& a) { + return apply_vector_unary>>::apply( + std::forward(a), [](const auto& v) { + return std::forward(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..b430671a399 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,7 +104,7 @@ 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, const T2& b) { return apply_scalar_binary( [](const auto& c, const auto& d) { return log_sum_exp(c, d); }, a, b); } diff --git a/stan/math/prim/fun/logit.hpp b/stan/math/prim/fun/logit.hpp index 3f6f7ce7a8c..4288f23e054 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,17 @@ 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) { - return apply_vector_unary>::apply( - v_ref, - [](const auto& v) { return (v.array() / (1 - v.array())).log(); }); + [](auto&& v_ref) { + return apply_vector_unary>>::apply( + std::forward(v_ref), [](const auto& v) { + return (std::forward(v).array() + / (1 - std::forward(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..0fa8ec8419f 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(); }); + return apply_vector_unary>::reduce( + std::forward(m), [](const auto& x) { return x.maxCoeff(); }); } } // namespace math diff --git a/stan/math/prim/fun/mdivide_left.hpp b/stan/math/prim/fun/mdivide_left.hpp index 14bcbe55ed6..0d6b8cb83eb 100644 --- a/stan/math/prim/fun/mdivide_left.hpp +++ b/stan/math/prim/fun/mdivide_left.hpp @@ -22,20 +22,23 @@ namespace math { */ template * = nullptr> -inline Eigen::Matrix, T1::RowsAtCompileTime, - T2::ColsAtCompileTime> -mdivide_left(const T1& A, const T2& b) { +inline Eigen::Matrix, std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime> +mdivide_left(T1&& A, T2&& b) { check_square("mdivide_left", "A", A); check_multiplicable("mdivide_left", "A", A, "b", b); if (A.size() == 0) { return {0, b.cols()}; } - return Eigen::Matrix, T1::RowsAtCompileTime, - T1::ColsAtCompileTime>(A) + return Eigen::Matrix, + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime>(std::forward(A)) .lu() - .solve(Eigen::Matrix, T2::RowsAtCompileTime, - T2::ColsAtCompileTime>(b)); + .solve(Eigen::Matrix, + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime>( + std::forward(b))); } } // namespace math diff --git a/stan/math/prim/fun/mdivide_left_ldlt.hpp b/stan/math/prim/fun/mdivide_left_ldlt.hpp index 0472dc4ca76..c007ba8919e 100644 --- a/stan/math/prim/fun/mdivide_left_ldlt.hpp +++ b/stan/math/prim/fun/mdivide_left_ldlt.hpp @@ -26,17 +26,18 @@ template * = nullptr, require_any_not_t>, is_fvar>>* = nullptr> inline Eigen::Matrix, Eigen::Dynamic, - EigMat::ColsAtCompileTime> -mdivide_left_ldlt(LDLT_factor& A, const EigMat& b) { + std::decay_t::ColsAtCompileTime> +mdivide_left_ldlt(LDLT_factor& A, EigMat&& b) { check_multiplicable("mdivide_left_ldlt", "A", A.matrix(), "b", b); if (A.matrix().cols() == 0) { return {0, b.cols()}; } - return A.ldlt().solve( - Eigen::Matrix, EigMat::RowsAtCompileTime, - EigMat::ColsAtCompileTime>(b)); + return A.ldlt().solve(Eigen::Matrix, + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime>( + std::forward(b))); } } // namespace math diff --git a/stan/math/prim/fun/mdivide_left_spd.hpp b/stan/math/prim/fun/mdivide_left_spd.hpp index 25b0f404fa0..1a2e2c4a14c 100644 --- a/stan/math/prim/fun/mdivide_left_spd.hpp +++ b/stan/math/prim/fun/mdivide_left_spd.hpp @@ -26,26 +26,25 @@ template * = nullptr, require_all_not_vt_var* = nullptr> inline Eigen::Matrix, - EigMat1::RowsAtCompileTime, EigMat2::ColsAtCompileTime> -mdivide_left_spd(const EigMat1& A, const EigMat2& b) { + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime> +mdivide_left_spd(EigMat1&& A, EigMat2&& b) { static constexpr const char* function = "mdivide_left_spd"; check_multiplicable(function, "A", A, "b", b); - const auto& A_ref = to_ref(A); + auto&& A_ref = to_ref(std::forward(A)); check_symmetric(function, "A", A_ref); check_not_nan(function, "A", A_ref); - if (A.size() == 0) { - return {0, b.cols()}; - } - - auto llt - = Eigen::Matrix, - EigMat1::RowsAtCompileTime, EigMat1::ColsAtCompileTime>( - A_ref) - .llt(); + auto llt = Eigen::Matrix, + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime>( + std::forward(A_ref)) + .llt(); check_pos_definite(function, "A", llt); - return llt.solve( - Eigen::Matrix, EigMat2::RowsAtCompileTime, - EigMat2::ColsAtCompileTime>(b)); + return std::move(llt).solve( + Eigen::Matrix, + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime>( + std::forward(b))); } } // namespace math diff --git a/stan/math/prim/fun/mdivide_left_tri.hpp b/stan/math/prim/fun/mdivide_left_tri.hpp index 695981e78ca..65bf893333c 100644 --- a/stan/math/prim/fun/mdivide_left_tri.hpp +++ b/stan/math/prim/fun/mdivide_left_tri.hpp @@ -24,9 +24,9 @@ namespace math { * match the size of A. */ template * = nullptr, - require_all_not_eigen_vt * = nullptr> -inline auto mdivide_left_tri(const T1 &A, const T2 &b) { + require_all_eigen_t* = nullptr, + require_all_not_eigen_vt* = nullptr> +inline auto mdivide_left_tri(T1&& A, T2&& b) { using T_return = return_type_t; using ret_type = Eigen::Matrix; check_square("mdivide_left_tri", "A", A); @@ -34,10 +34,9 @@ inline auto mdivide_left_tri(const T1 &A, const T2 &b) { if (A.rows() == 0) { return ret_type(0, b.cols()); } - - return ret_type(A) + return ret_type(std::forward(A)) .template triangularView() - .solve(ret_type(b)) + .solve(ret_type(std::forward(b))) .eval(); } @@ -50,8 +49,8 @@ inline auto mdivide_left_tri(const T1 &A, const T2 &b) { * @return x = A^-1 . * @throws std::domain_error if A is not square */ -template * = nullptr> -inline plain_type_t mdivide_left_tri(const T &A) { +template * = nullptr> +inline plain_type_t mdivide_left_tri(T&& A) { check_square("mdivide_left_tri", "A", A); if (A.rows() == 0) { return {}; diff --git a/stan/math/prim/fun/mdivide_left_tri_low.hpp b/stan/math/prim/fun/mdivide_left_tri_low.hpp index 19079549ae9..8f7c43f0394 100644 --- a/stan/math/prim/fun/mdivide_left_tri_low.hpp +++ b/stan/math/prim/fun/mdivide_left_tri_low.hpp @@ -28,27 +28,26 @@ namespace math { */ template * = nullptr, require_all_not_eigen_vt* = nullptr> -inline Eigen::Matrix, T1::RowsAtCompileTime, - T2::ColsAtCompileTime> -mdivide_left_tri_low(const T1& A, const T2& b) { +inline Eigen::Matrix, std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime> +mdivide_left_tri_low(T1&& A, T2&& b) { check_square("mdivide_left_tri_low", "A", A); check_multiplicable("mdivide_left_tri_low", "A", A, "b", b); if (A.rows() == 0) { return {0, b.cols()}; } - - return mdivide_left_tri(A, b); + return mdivide_left_tri(std::forward(A), + std::forward(b)); } template * = nullptr, require_not_eigen_vt* = nullptr> -inline plain_type_t mdivide_left_tri_low(const T& A) { +inline plain_type_t mdivide_left_tri_low(T&& A) { check_square("mdivide_left_tri_low", "A", A); if (A.rows() == 0) { return {}; } - - return mdivide_left_tri(A); + return mdivide_left_tri(std::forward(A)); } } // namespace math diff --git a/stan/math/prim/fun/mdivide_right.hpp b/stan/math/prim/fun/mdivide_right.hpp index fd699846792..33384296c14 100644 --- a/stan/math/prim/fun/mdivide_right.hpp +++ b/stan/math/prim/fun/mdivide_right.hpp @@ -24,24 +24,25 @@ template * = nullptr, require_all_not_vt_fvar* = nullptr> inline Eigen::Matrix, - EigMat1::RowsAtCompileTime, EigMat2::ColsAtCompileTime> -mdivide_right(const EigMat1& b, const EigMat2& A) { + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime> +mdivide_right(EigMat1&& b, EigMat2&& A) { using T_return = return_type_t; check_square("mdivide_right", "A", A); check_multiplicable("mdivide_right", "b", b, "A", A); if (A.size() == 0) { return {b.rows(), 0}; } - - return Eigen::Matrix(A) + return Eigen::Matrix::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime>( + std::forward(A)) .transpose() .lu() - .solve(Eigen::Matrix(b) + .solve(Eigen::Matrix( + std::forward(b)) .transpose()) .transpose(); } - } // namespace math } // namespace stan diff --git a/stan/math/prim/fun/mdivide_right_ldlt.hpp b/stan/math/prim/fun/mdivide_right_ldlt.hpp index 8ad77393a03..4d56be1b32c 100644 --- a/stan/math/prim/fun/mdivide_right_ldlt.hpp +++ b/stan/math/prim/fun/mdivide_right_ldlt.hpp @@ -24,11 +24,13 @@ namespace math { template * = nullptr, require_any_not_st_arithmetic* = nullptr> -inline auto mdivide_right_ldlt(const EigMat& b, LDLT_factor& A) { +inline auto mdivide_right_ldlt(EigMat&& b, LDLT_factor& A) { check_multiplicable("mdivide_right_ldlt", "b", b, "A", A.matrix()); check_ldlt_factor("mdivide_right_ldlt", "A", A); - return mdivide_left_ldlt(A, b.transpose()).transpose().eval(); + return mdivide_left_ldlt(A, std::forward(b).transpose()) + .transpose() + .eval(); } /** @@ -47,8 +49,9 @@ inline auto mdivide_right_ldlt(const EigMat& b, LDLT_factor& A) { template * = nullptr, require_all_st_arithmetic* = nullptr> -inline Eigen::Matrix -mdivide_right_ldlt(const EigMat& b, LDLT_factor& A) { +inline Eigen::Matrix::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime> +mdivide_right_ldlt(EigMat&& b, LDLT_factor& A) { check_multiplicable("mdivide_right_ldlt", "b", b, "A", A.matrix()); check_ldlt_factor("mdivide_right_ldlt", "A", A); @@ -56,7 +59,7 @@ mdivide_right_ldlt(const EigMat& b, LDLT_factor& A) { return {b.rows(), 0}; } - return A.ldlt().solve(b.transpose()).transpose(); + return A.ldlt().solve(std::forward(b).transpose()).transpose(); } } // namespace math diff --git a/stan/math/prim/fun/mdivide_right_spd.hpp b/stan/math/prim/fun/mdivide_right_spd.hpp index c3c177dbb26..2898a59304e 100644 --- a/stan/math/prim/fun/mdivide_right_spd.hpp +++ b/stan/math/prim/fun/mdivide_right_spd.hpp @@ -26,18 +26,17 @@ namespace math { template * = nullptr> inline Eigen::Matrix, - EigMat1::RowsAtCompileTime, EigMat2::ColsAtCompileTime> -mdivide_right_spd(const EigMat1& b, const EigMat2& A) { + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime> +mdivide_right_spd(EigMat1&& b, EigMat2&& A) { static constexpr const char* function = "mdivide_right_spd"; check_multiplicable(function, "b", b, "A", A); - const auto& A_ref = to_ref(A); + auto&& A_ref = to_ref(std::forward(A)); check_symmetric(function, "A", A_ref); check_not_nan(function, "A", A_ref); - if (A.size() == 0) { - return {b.rows(), 0}; - } - - return mdivide_left_spd(A_ref, b.transpose()).transpose(); + return mdivide_left_spd(std::forward(A_ref), + std::forward(b).transpose()) + .transpose(); } } // namespace math diff --git a/stan/math/prim/fun/mdivide_right_tri.hpp b/stan/math/prim/fun/mdivide_right_tri.hpp index 41ce153bf2a..ee68b1acd0b 100644 --- a/stan/math/prim/fun/mdivide_right_tri.hpp +++ b/stan/math/prim/fun/mdivide_right_tri.hpp @@ -26,7 +26,7 @@ namespace math { */ template * = nullptr> -inline auto mdivide_right_tri(const EigMat1& b, const EigMat2& A) { +inline auto mdivide_right_tri(EigMat1&& b, EigMat2&& A) { check_square("mdivide_right_tri", "A", A); check_multiplicable("mdivide_right_tri", "b", b, "A", A); if (TriView != Eigen::Lower && TriView != Eigen::Upper) { @@ -40,10 +40,10 @@ inline auto mdivide_right_tri(const EigMat1& b, const EigMat2& A) { return ret_type(b.rows(), 0); } - return ret_type(A) + return ret_type(std::forward(A)) .template triangularView() .transpose() - .solve(ret_type(b).transpose()) + .solve(ret_type(std::forward(b)).transpose()) .transpose() .eval(); } diff --git a/stan/math/prim/fun/mdivide_right_tri_low.hpp b/stan/math/prim/fun/mdivide_right_tri_low.hpp index 6a01573a016..f67e79b153b 100644 --- a/stan/math/prim/fun/mdivide_right_tri_low.hpp +++ b/stan/math/prim/fun/mdivide_right_tri_low.hpp @@ -25,9 +25,11 @@ template * = nullptr, require_all_not_vt_fvar* = nullptr> inline Eigen::Matrix, - EigMat1::RowsAtCompileTime, EigMat2::ColsAtCompileTime> -mdivide_right_tri_low(const EigMat1& b, const EigMat2& A) { - return mdivide_right_tri(b, A); + std::decay_t::RowsAtCompileTime, + std::decay_t::ColsAtCompileTime> +mdivide_right_tri_low(EigMat1&& b, EigMat2&& A) { + return mdivide_right_tri(std::forward(b), + std::forward(A)); } } // namespace math diff --git a/stan/math/prim/fun/mean.hpp b/stan/math/prim/fun/mean.hpp index aff32358d41..6101263c91b 100644 --- a/stan/math/prim/fun/mean.hpp +++ b/stan/math/prim/fun/mean.hpp @@ -19,10 +19,10 @@ 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, - [](const auto& a) { return a.mean(); }); + return apply_vector_unary>::reduce( + std::forward(m), [](const auto& a) { return a.mean(); }); } } // namespace math diff --git a/stan/math/prim/fun/min.hpp b/stan/math/prim/fun/min.hpp index 9d84a38ac93..ae1e14b44f5 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(); }); + return apply_vector_unary>::reduce( + 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..3822bdc0e22 100644 --- a/stan/math/prim/fun/minus.hpp +++ b/stan/math/prim/fun/minus.hpp @@ -15,8 +15,14 @@ namespace math { * @return Negation of subtrahend. */ template * = nullptr> -inline auto minus(const T& x) { - return -x; +inline auto minus(T&& x) { + if constexpr (is_eigen_v) { + return make_holder( + [](auto&& xx) { return -std::forward(xx); }, + std::forward(x)); + } else { + return -x; + } } /** @@ -26,12 +32,12 @@ 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), [](auto&& v) { + return -std::forward(v); + }); } - } // namespace math } // namespace stan 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.hpp b/stan/math/prim/fun/multiply.hpp index 59e220dcaf0..3e3668c5cc3 100644 --- a/stan/math/prim/fun/multiply.hpp +++ b/stan/math/prim/fun/multiply.hpp @@ -24,8 +24,10 @@ template * = nullptr, require_eigen_t* = nullptr, require_all_not_st_var* = nullptr, require_all_not_complex_t>* = nullptr> -inline auto multiply(const Mat& m, Scal c) { - return c * m; +inline auto multiply(Mat&& m, Scal c) { + return make_holder( + [c](auto&& m_) { return c * std::forward(m_); }, + std::forward(m)); } /** @@ -43,8 +45,10 @@ inline auto multiply(const Mat& m, Scal c) { template , Scal>* = nullptr, require_eigen_t* = nullptr, require_not_eigen_t* = nullptr> -inline auto multiply(const Mat& m, Scal c) { - return m * c; +inline auto multiply(Mat&& m, Scal c) { + return make_holder( + [c](auto&& m_) { return c * std::forward(m_); }, + std::forward(m)); } /** @@ -62,8 +66,10 @@ inline auto multiply(const Mat& m, Scal c) { template , Scal>* = nullptr, require_eigen_t* = nullptr, require_not_eigen_t* = nullptr> -inline auto multiply(const Scal& m, const Mat& c) { - return m * c; +inline auto multiply(const Scal& c, Mat&& m) { + return make_holder( + [c](auto&& m_) { return std::forward(m_) * c; }, + std::forward(m)); } /** @@ -80,8 +86,10 @@ template * = nullptr, require_eigen_t* = nullptr, require_all_not_st_var* = nullptr, require_all_not_complex_t>* = nullptr> -inline auto multiply(Scal c, const Mat& m) { - return c * m; +inline auto multiply(Scal c, Mat&& m) { + return make_holder( + [c](auto&& m_) { return c * std::forward(m_); }, + std::forward(m)); } /** @@ -101,10 +109,15 @@ inline auto multiply(Scal c, const Mat& m) { template * = nullptr, require_not_eigen_row_and_col_t* = nullptr> -inline auto multiply(const Mat1& m1, const Mat2& m2) { +inline auto multiply(Mat1&& m1, Mat2&& m2) { check_size_match("multiply", "Columns of m1", m1.cols(), "Rows of m2", m2.rows()); - return m1 * m2; + return make_holder( + [](auto&& m1_, auto&& m2_) { + return std::forward(m1_) + * std::forward(m2_); + }, + std::forward(m1), std::forward(m2)); } /** @@ -125,10 +138,15 @@ template * = nullptr, require_t>>* = nullptr, require_not_eigen_row_and_col_t* = nullptr> -inline auto multiply(const Mat1& m1, const Mat2& m2) { +inline auto multiply(Mat1&& m1, Mat2&& m2) { check_size_match("multiply", "Columns of m1", m1.cols(), "Rows of m2", m2.rows()); - return m1.lazyProduct(m2).eval(); + return make_holder( + [](auto&& m1_, auto&& m2_) { + return std::forward(m1_).lazyProduct( + std::forward(m2_)); + }, + std::forward(m1), std::forward(m2)); } /** @@ -147,9 +165,9 @@ inline auto multiply(const Mat1& m1, const Mat2& m2) { template >* = nullptr, require_eigen_row_and_col_t* = nullptr> -inline auto multiply(const RowVec& rv, const ColVec& v) { +inline auto multiply(RowVec&& rv, ColVec&& v) { check_multiplicable("multiply", "rv", rv, "v", v); - return dot_product(rv, v); + return dot_product(std::forward(rv), std::forward(v)); } /** 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..fd29bf4f70b 100644 --- a/stan/math/prim/fun/norm1.hpp +++ b/stan/math/prim/fun/norm1.hpp @@ -17,9 +17,9 @@ namespace math { * @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>(); +inline double norm1(T&& v) { + return make_holder([](auto&& v_) { return v_.template lpNorm<1>(); }, + std::forward(v)); } /** @@ -31,9 +31,10 @@ inline double norm1(const T& v) { * @return L1 norm of v. */ template * = nullptr> -inline auto norm1(const Container& x) { - return apply_vector_unary::reduce( - x, [](const auto& v) { return norm1(v); }); +inline auto norm1(Container&& x) { + return apply_vector_unary>::reduce( + std::forward(x), + [](auto&& v) { return norm1(std::forward(v)); }); } } // namespace math diff --git a/stan/math/prim/fun/norm2.hpp b/stan/math/prim/fun/norm2.hpp index 07040003943..5dbe0ed02b5 100644 --- a/stan/math/prim/fun/norm2.hpp +++ b/stan/math/prim/fun/norm2.hpp @@ -17,9 +17,9 @@ namespace math { * @return L2 norm of v. */ template * = nullptr> -inline double norm2(const T& v) { - ref_type_t v_ref = v; - return v_ref.template lpNorm<2>(); +inline double norm2(T&& v) { + return make_holder([](auto&& v_) { return v_.template lpNorm<2>(); }, + std::forward(v)); } /** @@ -31,9 +31,10 @@ inline double norm2(const T& v) { * @return L2 norm of v. */ template * = nullptr> -inline auto norm2(const Container& x) { - return apply_vector_unary::reduce( - x, [](const auto& v) { return norm2(v); }); +inline auto norm2(Container&& x) { + return apply_vector_unary>::reduce( + std::forward(x), + [](auto&& v) { return norm2(std::forward(v)); }); } } // 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/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/pseudo_eigenvalues.hpp b/stan/math/prim/fun/pseudo_eigenvalues.hpp index fd51f25f46e..7ad4d51cb2b 100644 --- a/stan/math/prim/fun/pseudo_eigenvalues.hpp +++ b/stan/math/prim/fun/pseudo_eigenvalues.hpp @@ -8,7 +8,8 @@ namespace stan { namespace math { template -Eigen::Matrix pseudo_eigenvalues(const Eigen::Matrix& m) { +inline Eigen::Matrix pseudo_eigenvalues( + const Eigen::Matrix& m) { check_nonzero_size("pseudo_eigenvalues", "m", m); check_square("pseudo_eigenvalues", "m", m); diff --git a/stan/math/prim/fun/quad_form.hpp b/stan/math/prim/fun/quad_form.hpp index 46cabbe601a..dff80db1bd4 100644 --- a/stan/math/prim/fun/quad_form.hpp +++ b/stan/math/prim/fun/quad_form.hpp @@ -52,11 +52,15 @@ template * = nullptr, require_eigen_col_vector_t* = nullptr, require_vt_same* = nullptr, require_all_vt_arithmetic* = nullptr> -inline value_type_t quad_form(const EigMat& A, const ColVec& B) { +inline value_type_t quad_form(EigMat&& A, ColVec&& B) { check_square("quad_form", "A", A); check_multiplicable("quad_form", "A", A, "B", B); - const auto& B_ref = to_ref(B); - return B_ref.dot(A * B_ref); + return make_holder( + [](auto&& b, auto&& a) { + auto&& b_ref = to_ref(std::forward(b)); + return b_ref.dot(a * b_ref); + }, + std::forward(B), std::forward(A)); } } // namespace math diff --git a/stan/math/prim/fun/quad_form_diag.hpp b/stan/math/prim/fun/quad_form_diag.hpp index d6db9ae58c1..e04ed9cd69b 100644 --- a/stan/math/prim/fun/quad_form_diag.hpp +++ b/stan/math/prim/fun/quad_form_diag.hpp @@ -10,15 +10,16 @@ namespace math { template * = nullptr, require_eigen_vector_t* = nullptr> -inline auto quad_form_diag(const EigMat& mat, const EigVec& vec) { +inline auto quad_form_diag(EigMat&& mat, EigVec&& vec) { check_square("quad_form_diag", "mat", mat); check_size_match("quad_form_diag", "rows of mat", mat.rows(), "size of vec", vec.size()); return make_holder( - [](const auto& v, const auto& x) { - return v.asDiagonal() * x * v.asDiagonal(); + [](auto&& mat_, auto&& vec_) { + return vec_.asDiagonal() * std::forward(mat_) + * vec_.asDiagonal(); }, - to_ref(vec), to_ref(mat)); + std::forward(mat), to_ref(std::forward(vec))); } } // namespace math diff --git a/stan/math/prim/fun/rank.hpp b/stan/math/prim/fun/rank.hpp index 9378a5c120b..2b8fd90544d 100644 --- a/stan/math/prim/fun/rank.hpp +++ b/stan/math/prim/fun/rank.hpp @@ -17,14 +17,14 @@ 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 (vec_ref.array() < vec_ref.coeff(s)).template cast().sum(); - }); + return apply_vector_unary>::reduce( + std::forward(v), [s](const auto& vec) { + auto&& vec_ref = to_ref(std::forward(vec)); + return (vec_ref.array() < vec_ref.coeff(s)).template cast().sum(); + }); } } // namespace math diff --git a/stan/math/prim/fun/read_corr_L.hpp b/stan/math/prim/fun/read_corr_L.hpp index 5e646ef82ae..152f1ad3d95 100644 --- a/stan/math/prim/fun/read_corr_L.hpp +++ b/stan/math/prim/fun/read_corr_L.hpp @@ -34,9 +34,9 @@ namespace math { * canonical partial correlations. */ template * = nullptr> -Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> read_corr_L( - const T& CPCs, // on (-1, 1) - size_t K) { +inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> +read_corr_L(const T& CPCs, // on (-1, 1) + size_t K) { using T_scalar = value_type_t; if (K == 0) { return {}; @@ -101,8 +101,8 @@ Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> read_corr_L( */ template * = nullptr, require_convertible_t, Lp>* = nullptr> -Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> read_corr_L( - const T& CPCs, size_t K, Lp& log_prob) { +inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> +read_corr_L(T&& CPCs, size_t K, Lp& log_prob) { using T_scalar = value_type_t; if (K == 0) { return {}; @@ -112,7 +112,7 @@ Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> read_corr_L( 1); } - const Eigen::Ref>& CPCs_ref = CPCs; + auto&& CPCs_ref = to_ref(std::forward(CPCs)); size_t pos = 0; T_scalar acc = 0; // no need to abs() because this Jacobian determinant diff --git a/stan/math/prim/fun/read_corr_matrix.hpp b/stan/math/prim/fun/read_corr_matrix.hpp index 53b6e2cdff8..7be0f328793 100644 --- a/stan/math/prim/fun/read_corr_matrix.hpp +++ b/stan/math/prim/fun/read_corr_matrix.hpp @@ -23,13 +23,13 @@ namespace math { * canonical partial correlations. */ template * = nullptr> -Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -read_corr_matrix(const T_CPCs& CPCs, size_t K) { +inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> +read_corr_matrix(T_CPCs&& CPCs, size_t K) { if (K == 0) { return {}; } - - return multiply_lower_tri_self_transpose(read_corr_L(CPCs, K)); + return multiply_lower_tri_self_transpose( + read_corr_L(std::forward(CPCs), K)); } /** @@ -56,13 +56,13 @@ read_corr_matrix(const T_CPCs& CPCs, size_t K) { template * = nullptr, require_convertible_t, Lp>* = nullptr> -Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -read_corr_matrix(const T_CPCs& CPCs, size_t K, Lp& log_prob) { +inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> +read_corr_matrix(T_CPCs&& CPCs, size_t K, Lp& log_prob) { if (K == 0) { return {}; } - - return multiply_lower_tri_self_transpose(read_corr_L(CPCs, K, log_prob)); + return multiply_lower_tri_self_transpose( + read_corr_L(std::forward(CPCs), K, log_prob)); } } // namespace math diff --git a/stan/math/prim/fun/read_cov_matrix.hpp b/stan/math/prim/fun/read_cov_matrix.hpp index 0e7e629845d..b7043d20666 100644 --- a/stan/math/prim/fun/read_cov_matrix.hpp +++ b/stan/math/prim/fun/read_cov_matrix.hpp @@ -30,7 +30,7 @@ read_cov_matrix(const T_CPCs& CPCs, const T_sds& sds, value_type_t& log_prob) { Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> L = read_cov_L(CPCs, sds, log_prob); - return multiply_lower_tri_self_transpose(L); + return multiply_lower_tri_self_transpose(std::move(L)); } /** @@ -53,7 +53,7 @@ read_cov_matrix(const T_CPCs& CPCs, const T_sds& sds) { D.diagonal() = sds; Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> L = D * read_corr_L(CPCs, K); - return multiply_lower_tri_self_transpose(L); + return multiply_lower_tri_self_transpose(std::move(L)); } } // namespace math diff --git a/stan/math/prim/fun/rep_matrix.hpp b/stan/math/prim/fun/rep_matrix.hpp index 7333ec3833d..c6311495471 100644 --- a/stan/math/prim/fun/rep_matrix.hpp +++ b/stan/math/prim/fun/rep_matrix.hpp @@ -21,10 +21,14 @@ namespace math { template * = nullptr, require_stan_scalar_t* = nullptr> -inline auto rep_matrix(const T& x, int m, int n) { +inline auto rep_matrix(T&& x, int m, int n) { check_nonnegative("rep_matrix", "rows", m); check_nonnegative("rep_matrix", "cols", n); - return Ret::Constant(m, n, x); + return make_holder( + [m, n](auto&& x_) { + return Ret::Constant(m, n, std::forward(x_)); + }, + std::forward(x)); } /** @@ -51,13 +55,15 @@ inline auto rep_matrix(const T& x, int m, int n) { * @param n Number of rows or columns. */ template * = nullptr> -inline auto rep_matrix(const Vec& x, int n) { - if (is_eigen_row_vector::value) { +inline auto rep_matrix(Vec&& x, int n) { + if constexpr (is_eigen_row_vector::value) { check_nonnegative("rep_matrix", "rows", n); - return x.replicate(n, 1); + return make_holder([n](auto&& xx) { return xx.replicate(n, 1); }, + std::forward(x)); } else { check_nonnegative("rep_matrix", "cols", n); - return x.replicate(1, n); + return make_holder([n](auto&& xx) { return xx.replicate(1, n); }, + std::forward(x)); } } diff --git a/stan/math/prim/fun/rep_row_vector.hpp b/stan/math/prim/fun/rep_row_vector.hpp index abc63e4a773..983e64aaabc 100644 --- a/stan/math/prim/fun/rep_row_vector.hpp +++ b/stan/math/prim/fun/rep_row_vector.hpp @@ -10,9 +10,13 @@ namespace math { template * = nullptr, require_stan_scalar_t* = nullptr> -inline auto rep_row_vector(const T& x, int n) { +inline auto rep_row_vector(T&& x, int n) { check_nonnegative("rep_vector", "n", n); - return T_ret::Constant(n, x); + return make_holder( + [n](auto&& x_) { + return T_ret::Constant(n, std::forward(x_)); + }, + std::forward(x)); } template * = nullptr> inline auto rep_row_vector(const T& x, int n) { diff --git a/stan/math/prim/fun/reverse.hpp b/stan/math/prim/fun/reverse.hpp index 82c58ca1d70..df0ca4a0531 100644 --- a/stan/math/prim/fun/reverse.hpp +++ b/stan/math/prim/fun/reverse.hpp @@ -32,8 +32,16 @@ inline std::vector reverse(const std::vector& x) { * @return Vector or row vector in reversed order. */ template > -inline auto reverse(const T& x) { - return x.reverse(); +inline auto reverse(T&& x) { + if constexpr (is_std_vector_v) { + // If std::vector + std::decay_t rev(x.size()); + std::reverse_copy(x.begin(), x.end(), rev.begin()); + return rev; + } else { + return make_holder([](auto&& xx) { return xx.reverse(); }, + std::forward(x)); + } } } // 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..7fe488adceb 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,8 @@ 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) { + return round(std::forward(x)); } }; @@ -35,9 +39,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 +56,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), + [](auto&& v) { return std::forward(v).array().round(); }); } } // namespace math diff --git a/stan/math/prim/fun/row.hpp b/stan/math/prim/fun/row.hpp index 9e4ce94f33a..a48f343e8ef 100644 --- a/stan/math/prim/fun/row.hpp +++ b/stan/math/prim/fun/row.hpp @@ -21,10 +21,11 @@ namespace math { * @throw std::out_of_range if i is out of range. */ template * = nullptr> -inline auto row(const T& m, size_t i) { +inline auto row(T&& m, size_t i) { check_row_index("row", "i", m, i); - - return m.row(i - 1); + return make_holder( + [i](auto&& mm) { return std::forward(mm).row(i - 1); }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/rows.hpp b/stan/math/prim/fun/rows.hpp index b6e5f9925fe..d9a3ef980bc 100644 --- a/stan/math/prim/fun/rows.hpp +++ b/stan/math/prim/fun/rows.hpp @@ -17,8 +17,10 @@ namespace math { * @return Number of rows. */ template * = nullptr> -inline int64_t rows(const T& m) { - return m.rows(); +inline int64_t rows(T&& m) { + return make_holder( + [](auto&& mm) { return std::forward(mm).rows(); }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/rows_dot_product.hpp b/stan/math/prim/fun/rows_dot_product.hpp index a7afa6aa8bd..8b2b2c28fa3 100644 --- a/stan/math/prim/fun/rows_dot_product.hpp +++ b/stan/math/prim/fun/rows_dot_product.hpp @@ -24,10 +24,18 @@ namespace math { template * = nullptr, require_all_not_eigen_vt* = nullptr> -inline Eigen::Matrix, Mat1::RowsAtCompileTime, 1> -rows_dot_product(const Mat1& v1, const Mat2& v2) { +inline Eigen::Matrix, + std::decay_t::RowsAtCompileTime, 1> +rows_dot_product(Mat1&& v1, Mat2&& v2) { check_matching_dims("rows_dot_product", "v1", v1, "v2", v2); - return (v1.cwiseProduct(v2)).rowwise().sum(); + return make_holder( + [](auto&& v1, auto&& v2) { + return (std::forward(v1).cwiseProduct( + std::forward(v2))) + .rowwise() + .sum(); + }, + std::forward(v1), std::forward(v2)); } } // namespace math diff --git a/stan/math/prim/fun/rows_dot_self.hpp b/stan/math/prim/fun/rows_dot_self.hpp index 06d0af10de0..0f89aa0963e 100644 --- a/stan/math/prim/fun/rows_dot_self.hpp +++ b/stan/math/prim/fun/rows_dot_self.hpp @@ -17,9 +17,12 @@ namespace math { */ template * = nullptr, require_not_st_var* = nullptr> -inline Eigen::Matrix, T::RowsAtCompileTime, 1> rows_dot_self( - const T& x) { - return x.rowwise().squaredNorm(); +inline auto rows_dot_self(T&& x) { + return make_holder( + [](const auto& xx) { + return std::forward(xx).rowwise().squaredNorm(); + }, + std::forward(x)); } } // namespace math diff --git a/stan/math/prim/fun/sd.hpp b/stan/math/prim/fun/sd.hpp index 39223a6135b..96da88c00f9 100644 --- a/stan/math/prim/fun/sd.hpp +++ b/stan/math/prim/fun/sd.hpp @@ -23,18 +23,16 @@ 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) { - check_nonzero_size("sd", "x", x); - - if (x.size() == 1) { - return scalar_type_t(0.0); - } - - return sqrt(variance(x)); - }); + return apply_vector_unary>::reduce( + std::forward(m), [](auto&& x) { + check_nonzero_size("sd", "x", x); + if (x.size() == 1) { + return scalar_type_t(0.0); + } + return sqrt(variance(std::forward(x))); + }); } } // namespace math diff --git a/stan/math/prim/fun/segment.hpp b/stan/math/prim/fun/segment.hpp index 38ef04a1697..62d552bb121 100644 --- a/stan/math/prim/fun/segment.hpp +++ b/stan/math/prim/fun/segment.hpp @@ -15,7 +15,7 @@ namespace math { * @tparam T type of the vector */ template * = nullptr> -inline auto segment(const Vec& v, size_t i, size_t n) { +inline auto segment(Vec&& v, size_t i, size_t n) { check_greater("segment", "n", i, 0.0); check_less_or_equal("segment", "n", i, static_cast(v.size())); if (n != 0) { @@ -23,23 +23,16 @@ inline auto segment(const Vec& v, size_t i, size_t n) { check_less_or_equal("segment", "n", i + n - 1, static_cast(v.size())); } - return v.segment(i - 1, n); -} - -template -std::vector segment(const std::vector& sv, size_t i, size_t n) { - check_greater("segment", "i", i, 0.0); - check_less_or_equal("segment", "i", i, sv.size()); - if (n != 0) { - check_greater("segment", "i+n-1", i + n - 1, 0.0); - check_less_or_equal("segment", "i+n-1", i + n - 1, - static_cast(sv.size())); - } - std::vector s; - for (size_t j = 0; j < n; ++j) { - s.push_back(sv[i + j - 1]); + if constexpr (is_std_vector_v) { + std::decay_t s; + for (size_t j = 0; j < n; ++j) { + s.push_back(v[i + j - 1]); + } + return s; + } else { + return make_holder([i, n](auto&& v_) { return v_.segment(i - 1, n); }, + std::forward(v)); } - return s; } } // namespace math diff --git a/stan/math/prim/fun/select.hpp b/stan/math/prim/fun/select.hpp index def8bd3d67c..7f4ae51d151 100644 --- a/stan/math/prim/fun/select.hpp +++ b/stan/math/prim/fun/select.hpp @@ -23,8 +23,7 @@ namespace math { template , require_all_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, T_false&& y_false) { return c ? ReturnT(y_true) : ReturnT(y_false); } @@ -80,16 +79,15 @@ 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, T_false&& y_false) { if (c) { return y_true; } else { return apply_scalar_binary( - [](const auto& y_true_inner, const auto& y_false_inner) { - return y_false_inner; + [](auto&& y_true_inner, auto&& y_false_inner) { + return std::forward(y_false_inner); }, - y_true, y_false); + std::forward(y_true), std::forward(y_false)); } } @@ -115,16 +113,15 @@ 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; + [](auto&& y_true_inner, auto&& y_false_inner) { + return std::forward(y_true_inner); }, - y_true, y_false); + T_true(y_true), std::forward(y_false)); } else { - return y_false; + return std::forward(y_false); } } @@ -146,13 +143,16 @@ inline ReturnT select(const bool c, const T_true y_true, template * = nullptr, require_all_stan_scalar_t* = nullptr> -inline auto select(const T_bool c, const T_true y_true, const T_false y_false) { +inline auto select(T_bool&& c, const T_true y_true, const T_false y_false) { using ret_t = return_type_t; - return c - .unaryExpr([y_true, y_false](bool cond) { - return cond ? ret_t(y_true) : ret_t(y_false); - }) - .eval(); + return make_holder( + [y_true, y_false](auto&& c_) { + return std::forward(c_).unaryExpr( + [y_true, y_false](bool cond) { + return cond ? ret_t(y_true) : ret_t(y_false); + }); + }, + std::forward(c)); } /** @@ -170,11 +170,20 @@ inline auto select(const T_bool c, const T_true y_true, const T_false y_false) { template * = nullptr, require_any_eigen_array_t* = nullptr> -inline auto select(const T_bool c, const T_true y_true, const T_false y_false) { +inline auto select(T_bool&& c, T_true&& y_true, T_false&& y_false) { check_consistent_sizes("select", "boolean", c, "left hand side", y_true, "right hand side", y_false); using ret_t = return_type_t; - return c.select(y_true, y_false).template cast().eval(); + return make_holder( + [](auto&& c_, auto&& y_true_, auto&& y_false_) { + return std::forward(c_) + .select(std::forward(y_true_), + std::forward(y_false_)) + .template cast() + .eval(); + }, + std::forward(c), std::forward(y_true), + std::forward(y_false)); } } // namespace math 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..85b3f79dd57 100644 --- a/stan/math/prim/fun/sin.hpp +++ b/stan/math/prim/fun/sin.hpp @@ -46,8 +46,8 @@ 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) { + return sin(std::forward(x)); } }; @@ -59,8 +59,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 +73,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), + [&](auto&& v) { return std::forward(v).array().sin(); }); } namespace internal { diff --git a/stan/math/prim/fun/singular_values.hpp b/stan/math/prim/fun/singular_values.hpp index 7ade631048f..bdac47b559d 100644 --- a/stan/math/prim/fun/singular_values.hpp +++ b/stan/math/prim/fun/singular_values.hpp @@ -20,13 +20,18 @@ namespace math { */ template * = nullptr, require_not_st_var* = nullptr> -auto singular_values(const EigMat& m) { +inline auto singular_values(EigMat&& m) { if (unlikely(m.size() == 0)) { return Eigen::Matrix, Eigen::Dynamic, 1>(0, 1); } - return Eigen::JacobiSVD, Eigen::Dynamic, - Eigen::Dynamic> >(m) - .singularValues(); + return make_holder( + [](auto&& m_) { + return Eigen::JacobiSVD, + Eigen::Dynamic, Eigen::Dynamic>>( + std::forward(m_)) + .singularValues(); + }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/sinh.hpp b/stan/math/prim/fun/sinh.hpp index e3e55fa7477..d080ff78339 100644 --- a/stan/math/prim/fun/sinh.hpp +++ b/stan/math/prim/fun/sinh.hpp @@ -44,8 +44,8 @@ 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) { + return sinh(std::forward(x)); } }; @@ -57,8 +57,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 +72,10 @@ 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 std::forward(v).array().sinh(); }); } namespace internal { diff --git a/stan/math/prim/fun/sqrt.hpp b/stan/math/prim/fun/sqrt.hpp index 3e1620d2a61..59f15adaafe 100644 --- a/stan/math/prim/fun/sqrt.hpp +++ b/stan/math/prim/fun/sqrt.hpp @@ -44,8 +44,8 @@ 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) { + return sqrt(std::forward(x)); } }; @@ -57,8 +57,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 +73,10 @@ 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 std::forward(v).array().sqrt(); }); } namespace internal { diff --git a/stan/math/prim/fun/square.hpp b/stan/math/prim/fun/square.hpp index cb14bd77c8b..53dd3b68076 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,10 @@ 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 std::forward(v).array().square(); }); } } // namespace math diff --git a/stan/math/prim/fun/step.hpp b/stan/math/prim/fun/step.hpp index c75d164fd2b..c8eb85b470a 100644 --- a/stan/math/prim/fun/step.hpp +++ b/stan/math/prim/fun/step.hpp @@ -44,8 +44,8 @@ struct step_fun { * @return step(y) */ template - static inline auto fun(const T& y) { - return step(y); + static inline auto fun(T&& y) { + return step(std::forward(y)); } }; @@ -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/sub_col.hpp b/stan/math/prim/fun/sub_col.hpp index 109a73108f0..243b3c7ae64 100644 --- a/stan/math/prim/fun/sub_col.hpp +++ b/stan/math/prim/fun/sub_col.hpp @@ -20,13 +20,17 @@ namespace math { template < typename T, require_matrix_t* = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto sub_col(const T& m, size_t i, size_t j, size_t nrows) { +inline auto sub_col(T&& m, size_t i, size_t j, size_t nrows) { check_row_index("sub_col", "i", m, i); if (nrows > 0) { check_row_index("sub_col", "i+nrows-1", m, i + nrows - 1); } check_column_index("sub_col", "j", m, j); - return m.col(j - 1).segment(i - 1, nrows); + return make_holder( + [i, j, nrows](auto&& m_) { + return std::forward(m_).col(j - 1).segment(i - 1, nrows); + }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/sub_row.hpp b/stan/math/prim/fun/sub_row.hpp index 737cbd16953..971972301a9 100644 --- a/stan/math/prim/fun/sub_row.hpp +++ b/stan/math/prim/fun/sub_row.hpp @@ -20,13 +20,17 @@ namespace math { template < typename T, require_matrix_t* = nullptr, require_all_not_nonscalar_prim_or_rev_kernel_expression_t* = nullptr> -inline auto sub_row(const T& m, size_t i, size_t j, size_t ncols) { +inline auto sub_row(T&& m, size_t i, size_t j, size_t ncols) { check_row_index("sub_row", "i", m, i); check_column_index("sub_row", "j", m, j); if (ncols > 0) { check_column_index("sub_col", "j+ncols-1", m, j + ncols - 1); } - return m.row(i - 1).segment(j - 1, ncols); + return make_holder( + [i, j, ncols](auto&& m_) { + return std::forward(m_).row(i - 1).segment(j - 1, ncols); + }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/subtract.hpp b/stan/math/prim/fun/subtract.hpp index 4db3099e86e..3b94c5cc3c9 100644 --- a/stan/math/prim/fun/subtract.hpp +++ b/stan/math/prim/fun/subtract.hpp @@ -40,9 +40,14 @@ inline return_type_t subtract(const ScalarA& a, template * = nullptr, require_all_not_st_var* = nullptr> -inline auto subtract(const Mat1& m1, const Mat2& m2) { +inline auto subtract(Mat1&& m1, Mat2&& m2) { check_matching_dims("subtract", "m1", m1, "m2", m2); - return m1 - m2; + return make_holder( + [](auto&& m1_, auto&& m2_) { + return std::forward(m1_) + - std::forward(m2_); + }, + std::forward(m1), std::forward(m2)); } /** @@ -58,8 +63,12 @@ inline auto subtract(const Mat1& m1, const Mat2& m2) { template * = nullptr, require_eigen_t* = nullptr, require_all_not_st_var* = nullptr> -inline auto subtract(const Scal c, const Mat& m) { - return (c - m.array()).matrix(); +inline auto subtract(const Scal c, Mat&& m) { + return make_holder( + [c](auto&& m_) { + return (c - std::forward(m_).array()).matrix(); + }, + std::forward(m)); } /** @@ -75,8 +84,12 @@ inline auto subtract(const Scal c, const Mat& m) { template * = nullptr, require_stan_scalar_t* = nullptr, require_all_not_st_var* = nullptr> -inline auto subtract(const Mat& m, const Scal c) { - return (m.array() - c).matrix(); +inline auto subtract(Mat&& m, const Scal c) { + return make_holder( + [c](auto&& m_) { + return (std::forward(m_).array() - c).matrix(); + }, + std::forward(m)); } } // namespace math diff --git a/stan/math/prim/fun/symmetrize_from_lower_tri.hpp b/stan/math/prim/fun/symmetrize_from_lower_tri.hpp index 8d8a7927812..60b3ccab9ae 100644 --- a/stan/math/prim/fun/symmetrize_from_lower_tri.hpp +++ b/stan/math/prim/fun/symmetrize_from_lower_tri.hpp @@ -17,9 +17,9 @@ namespace math { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -symmetrize_from_lower_tri(const T& m) { +symmetrize_from_lower_tri(T&& m) { check_square("symmetrize_from_lower_tri", "m", m); - return m.template selfadjointView(); + return std::forward(m).template selfadjointView(); } } // namespace math diff --git a/stan/math/prim/fun/symmetrize_from_upper_tri.hpp b/stan/math/prim/fun/symmetrize_from_upper_tri.hpp index fc10a08d2ef..14d09878460 100644 --- a/stan/math/prim/fun/symmetrize_from_upper_tri.hpp +++ b/stan/math/prim/fun/symmetrize_from_upper_tri.hpp @@ -17,9 +17,9 @@ namespace math { */ template * = nullptr> inline Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic> -symmetrize_from_upper_tri(const T& m) { +symmetrize_from_upper_tri(T&& m) { check_square("symmetrize_from_upper_tri", "m", m); - return m.template selfadjointView(); + return std::forward(m).template selfadjointView(); } } // namespace math diff --git a/stan/math/prim/fun/tail.hpp b/stan/math/prim/fun/tail.hpp index 09697a91799..f4d50a26320 100644 --- a/stan/math/prim/fun/tail.hpp +++ b/stan/math/prim/fun/tail.hpp @@ -20,30 +20,21 @@ namespace math { * @throw std::out_of_range if n is out of range. */ template * = nullptr> -inline auto tail(const T& v, size_t n) { - if (n != 0) { - check_vector_index("tail", "n", v, n); +inline auto tail(T&& v, size_t n) { + if constexpr (is_std_vector_v) { + if (n != 0) { + check_std_vector_index("tail", "n", v, n); + } + std::decay_t s(v.end() - n, v.end()); + return s; + } else { + if (n != 0) { + check_vector_index("tail", "n", v, n); + } + return make_holder( + [n](auto&& v_) { return std::forward(v_).tail(n); }, + std::forward(v)); } - return v.tail(n); -} - -/** - * Return the specified number of elements as a standard vector - * from the back of the specified standard vector. - * - * @tparam T type of elements in the vector - * @param sv Standard vector. - * @param n Size of return. - * @return The last n elements of sv. - * @throw std::out_of_range if n is out of range. - */ -template -std::vector tail(const std::vector& sv, size_t n) { - if (n != 0) { - check_std_vector_index("tail", "n", sv, n); - } - std::vector s(sv.end() - n, sv.end()); - return s; } } // namespace math diff --git a/stan/math/prim/fun/tan.hpp b/stan/math/prim/fun/tan.hpp index 373672eb0c8..71ad4a04bbb 100644 --- a/stan/math/prim/fun/tan.hpp +++ b/stan/math/prim/fun/tan.hpp @@ -46,8 +46,8 @@ 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) { + return tan(std::forward(x)); } }; @@ -59,8 +59,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 +74,10 @@ 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 std::forward(v).array().tan(); }); } namespace internal { diff --git a/stan/math/prim/fun/tanh.hpp b/stan/math/prim/fun/tanh.hpp index 1ae3faff087..543c6d923fd 100644 --- a/stan/math/prim/fun/tanh.hpp +++ b/stan/math/prim/fun/tanh.hpp @@ -46,8 +46,8 @@ 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) { + return tanh(std::forward(x)); } }; @@ -59,8 +59,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 +74,10 @@ 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 std::forward(v).array().tanh(); }); } namespace internal { diff --git a/stan/math/prim/fun/tgamma.hpp b/stan/math/prim/fun/tgamma.hpp index c038b699ab7..64dad1b7a6d 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_not_var_matrix_t* = nullptr, require_container_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/trace_gen_quad_form.hpp b/stan/math/prim/fun/trace_gen_quad_form.hpp index 63a0a5a8a10..ad99f63d23c 100644 --- a/stan/math/prim/fun/trace_gen_quad_form.hpp +++ b/stan/math/prim/fun/trace_gen_quad_form.hpp @@ -33,13 +33,19 @@ template , typename = require_all_not_vt_var, typename = require_any_not_vt_arithmetic> -inline auto trace_gen_quad_form(const TD& D, const TA& A, const TB& B) { +inline auto trace_gen_quad_form(TD&& D, TA&& A, TB&& B) { check_square("trace_gen_quad_form", "A", A); check_square("trace_gen_quad_form", "D", D); check_multiplicable("trace_gen_quad_form", "A", A, "B", B); check_multiplicable("trace_gen_quad_form", "B", B, "D", D); - const auto& B_ref = to_ref(B); - return multiply(B_ref, D.transpose()).cwiseProduct(multiply(A, B_ref)).sum(); + return make_holder( + [](auto&& D_, auto&& A_, auto&& B_) { + auto&& B_ref = to_ref(std::forward(B_)); + return multiply(B_ref, std::forward(D_).transpose()) + .cwiseProduct(multiply(std::forward(A_), B_ref)) + .sum(); + }, + std::forward(D), std::forward(A), std::forward(B)); } /** diff --git a/stan/math/prim/fun/transpose.hpp b/stan/math/prim/fun/transpose.hpp index 39cb2dcaf73..f42868dd970 100644 --- a/stan/math/prim/fun/transpose.hpp +++ b/stan/math/prim/fun/transpose.hpp @@ -14,8 +14,10 @@ namespace math { * @return transposed matrix */ template * = nullptr> -auto inline transpose(const T& m) { - return m.transpose(); +auto inline transpose(T&& m) { + return make_holder( + [](auto&& m_) { return std::forward(m_).transpose(); }, + std::forward(m)); } } // 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..b6fbd0db071 100644 --- a/stan/math/prim/fun/trunc.hpp +++ b/stan/math/prim/fun/trunc.hpp @@ -8,6 +8,11 @@ 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 +26,8 @@ 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) { + return trunc(std::forward(x)); } }; @@ -37,10 +41,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/fun/uniform_simplex.hpp b/stan/math/prim/fun/uniform_simplex.hpp index bc18d34f9ad..cd760271630 100644 --- a/stan/math/prim/fun/uniform_simplex.hpp +++ b/stan/math/prim/fun/uniform_simplex.hpp @@ -17,7 +17,8 @@ namespace math { */ inline auto uniform_simplex(int K) { check_positive("uniform_simplex", "size", K); - return Eigen::VectorXd::Constant(K, 1.0 / K); + return make_holder( + [](int K) { return Eigen::VectorXd::Constant(K, 1.0 / K); }, K); } } // namespace math diff --git a/stan/math/prim/fun/variance.hpp b/stan/math/prim/fun/variance.hpp index 072be627b1c..2691b8beac6 100644 --- a/stan/math/prim/fun/variance.hpp +++ b/stan/math/prim/fun/variance.hpp @@ -22,9 +22,9 @@ namespace math { */ template * = nullptr, require_not_vt_var* = nullptr> -inline value_type_t variance(const EigMat& m) { +inline value_type_t variance(EigMat&& m) { using value_t = value_type_t; - const auto& mat = to_ref(m); + auto&& mat = to_ref(std::forward(m)); check_nonzero_size("variance", "m", mat); if (mat.size() == 1) { return value_t{0.0}; diff --git a/stan/math/prim/fun/zeros_vector.hpp b/stan/math/prim/fun/zeros_vector.hpp index f4cf80e3589..f23ee3931ae 100644 --- a/stan/math/prim/fun/zeros_vector.hpp +++ b/stan/math/prim/fun/zeros_vector.hpp @@ -16,7 +16,7 @@ namespace math { */ inline auto zeros_vector(int K) { check_nonnegative("zeros_vector", "size", K); - return Eigen::VectorXd::Zero(K); + return make_holder([](int k) { return Eigen::VectorXd::Zero(k); }, K); } } // 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/conjunction.hpp b/stan/math/prim/meta/conjunction.hpp index 19733e3ee90..213decb1a13 100644 --- a/stan/math/prim/meta/conjunction.hpp +++ b/stan/math/prim/meta/conjunction.hpp @@ -17,6 +17,9 @@ template struct conjunction : std::conditional_t, std::false_type> {}; +template