Skip to content

Use Perfect Forwarding in all functions that use apply family of functors #3221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
df9a9b2
First pass and passes mix fun test
SteveBronder Jul 9, 2025
b6e0a45
apply_scalar_binary. loglogistic now passes
SteveBronder Jul 11, 2025
13c4fd0
fix apply vector
SteveBronder Jul 11, 2025
dd3458c
update ternary
SteveBronder Jul 11, 2025
45128f6
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Jul 11, 2025
aa5eb5e
fix docs
SteveBronder Jul 11, 2025
6ff0b0e
fix docs
SteveBronder Jul 11, 2025
4edea9f
update test_ad_test to not use apply::return_t
SteveBronder Jul 11, 2025
696d2b2
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Jul 11, 2025
2c8c9c5
fix template for sub_col and sub_row
SteveBronder Jul 11, 2025
2c1a328
update log1m_exp template constraints
SteveBronder Jul 12, 2025
912855d
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Jul 12, 2025
dce5a63
fix templates for var and var matrix funs
SteveBronder Jul 12, 2025
fd7ad01
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Jul 12, 2025
021e150
fix exp2
SteveBronder Jul 12, 2025
c677470
fix exp2
SteveBronder Jul 12, 2025
a77c2b6
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Jul 12, 2025
f385fd2
remover binary operators for +/- etc from holder
SteveBronder Jul 12, 2025
1d5a64c
make operators for holder into free functions
SteveBronder Jul 14, 2025
f5f0ead
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Jul 14, 2025
e884013
have expr test on jenkins use gcc with sanitizer
SteveBronder Jul 14, 2025
57cd3bf
revert before merge: have expr test on jenkins use gcc with sanitizer…
SteveBronder Jul 14, 2025
b7336d2
fix templates for trigamma
SteveBronder Jul 15, 2025
ac2aa50
revert changes to jenkinsfile
SteveBronder Jul 15, 2025
5b87798
remove using boost::math::lgamma from prob functions to avoid name clash
SteveBronder Jul 15, 2025
c9c088e
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
stan-buildbot Jul 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions stan/math/fwd/fun/inv_logit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ namespace math {
* @param x argument
* @return inverse logit of argument
*/
template <typename T>
inline fvar<T> inv_logit(const fvar<T>& x) {
return fvar<T>(inv_logit(x.val_),
x.d_ * inv_logit(x.val_) * (1 - inv_logit(x.val_)));
template <typename T, require_fvar_t<T>* = nullptr>
inline auto inv_logit(T&& x) {
return std::decay_t<T>(inv_logit(x.val_),
x.d_ * inv_logit(x.val_) * (1 - inv_logit(x.val_)));
}

} // namespace math
Expand Down
9 changes: 6 additions & 3 deletions stan/math/fwd/functor/apply_scalar_unary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,23 @@ namespace math {
* autodiff variable.
*/
template <typename F, typename T>
struct apply_scalar_unary<F, fvar<T> > {
struct apply_scalar_unary<F, T, require_fvar_t<T>> {
/**
* Function return type, which is same as the argument type for
* the function, <code>fvar&lt;T&gt;</code>.
*/
using return_t = fvar<T>;
using return_t = std::decay_t<T>;

/**
* Apply the function specified by F to the specified argument.
*
* @param x Argument variable.
* @return Function applied to the variable.
*/
static inline return_t apply(const fvar<T>& x) { return F::fun(x); }
template <typename T2>
static inline auto apply(T2&& x) {
return F::fun(std::forward<T2>(x));
}
};

} // namespace math
Expand Down
1 change: 1 addition & 0 deletions stan/math/opencl/prim/dirichlet_lpdf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define STAN_MATH_OPENCL_PRIM_DIRICHLET_LPDF_HPP
#ifdef STAN_OPENCL

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/constants.hpp>
Expand Down
1 change: 1 addition & 0 deletions stan/math/prim/core/complex_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace math {
template <typename ValueType>
class complex_base {
public:
auto __rep() const { return *this; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't figure out from searching what this would do

/**
* Type of real and imaginary parts
*/
Expand Down
10 changes: 5 additions & 5 deletions stan/math/prim/fun/Phi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ inline double Phi(double x) {
*/
struct Phi_fun {
template <typename T>
static inline auto fun(const T& x) {
return Phi(x);
static inline auto fun(T&& x) {
return Phi(std::forward<T>(x));
}
};

Expand All @@ -66,9 +66,9 @@ struct Phi_fun {
template <
typename T,
require_all_not_nonscalar_prim_or_rev_kernel_expression_t<T>* = nullptr,
require_not_var_matrix_t<T>* = nullptr>
inline auto Phi(const T& x) {
return apply_scalar_unary<Phi_fun, T>::apply(x);
require_container_t<T>* = nullptr, require_not_var_matrix_t<T>* = nullptr>
inline auto Phi(T&& x) {
return apply_scalar_unary<Phi_fun, T>::apply(std::forward<T>(x));
}

} // namespace math
Expand Down
10 changes: 5 additions & 5 deletions stan/math/prim/fun/Phi_approx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ struct Phi_approx_fun {
* @return approximate value of Phi applied to argument
*/
template <typename T>
static inline auto fun(const T& x) {
return Phi_approx(x);
static inline auto fun(T&& x) {
return Phi_approx(std::forward<T>(x));
}
};

Expand All @@ -65,9 +65,9 @@ struct Phi_approx_fun {
template <
typename T,
require_all_not_nonscalar_prim_or_rev_kernel_expression_t<T>* = nullptr,
require_not_var_matrix_t<T>* = nullptr>
inline auto Phi_approx(const T& x) {
return apply_scalar_unary<Phi_approx_fun, T>::apply(x);
require_container_t<T>* = nullptr, require_not_var_matrix_t<T>* = nullptr>
inline auto Phi_approx(T&& x) {
return apply_scalar_unary<Phi_approx_fun, T>::apply(std::forward<T>(x));
}

} // namespace math
Expand Down
22 changes: 14 additions & 8 deletions stan/math/prim/fun/abs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace math {
* @return absolute value of argument
*/
template <typename T, require_arithmetic_t<T>* = nullptr>
inline T abs(T x) {
inline auto abs(T&& x) {
return std::abs(x);
}

Expand All @@ -35,7 +35,7 @@ inline T abs(T x) {
* @return absolute value of argument (a real number)
*/
template <typename T, require_complex_bt<std::is_arithmetic, T>* = nullptr>
inline auto abs(T x) {
inline auto abs(T&& x) {
return std::hypot(x.real(), x.imag());
}

Expand All @@ -49,8 +49,12 @@ inline auto abs(T x) {
*/
struct abs_fun {
template <typename T>
static inline auto fun(const T& x) {
return abs(x);
static inline auto fun(T&& x) {
if constexpr (std::is_arithmetic_v<std::decay_t<T>>) {
return std::abs(x);
} else {
return abs(std::forward<T>(x));
}
}
};

Expand All @@ -63,8 +67,9 @@ struct abs_fun {
* @return Absolute value of each variable in the container.
*/
template <typename Container, require_ad_container_t<Container>* = nullptr>
inline auto abs(const Container& x) {
return apply_scalar_unary<abs_fun, Container>::apply(x);
inline auto abs(Container&& x) {
return apply_scalar_unary<abs_fun, Container>::apply(
std::forward<Container>(x));
}

/**
Expand All @@ -77,9 +82,10 @@ inline auto abs(const Container& x) {
*/
template <typename Container,
require_container_bt<std::is_arithmetic, Container>* = nullptr>
inline auto abs(const Container& x) {
inline auto abs(Container&& x) {
return apply_vector_unary<Container>::apply(
x, [&](const auto& v) { return v.array().abs(); });
std::forward<Container>(x),
[&](const auto& v) { return v.array().abs(); });
}

namespace internal {
Expand Down
21 changes: 13 additions & 8 deletions stan/math/prim/fun/acos.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace math {
* @return arc cosine of the argument
*/
template <typename T, require_arithmetic_t<T>* = nullptr>
inline auto acos(const T x) {
inline auto acos(T&& x) {
return std::acos(x);
}

Expand All @@ -38,7 +38,7 @@ inline auto acos(const T x) {
* @return arc cosine of the argument
*/
template <typename T, require_complex_bt<std::is_arithmetic, T>* = nullptr>
inline auto acos(const T x) {
inline auto acos(T&& x) {
return std::acos(x);
}

Expand All @@ -51,8 +51,12 @@ inline auto acos(const T x) {
*/
struct acos_fun {
template <typename T>
static inline auto fun(const T& x) {
return acos(x);
static inline auto fun(T&& x) {
if constexpr (std::is_arithmetic_v<std::decay_t<T>>) {
return std::acos(x);
} else {
return acos(std::forward<T>(x));
}
}
};

Expand All @@ -65,8 +69,9 @@ struct acos_fun {
* @return Arc cosine of each variable in the container, in radians.
*/
template <typename Container, require_ad_container_t<Container>* = nullptr>
inline auto acos(const Container& x) {
return apply_scalar_unary<acos_fun, Container>::apply(x);
inline auto acos(Container&& x) {
return apply_scalar_unary<acos_fun, Container>::apply(
std::forward<Container>(x));
}

/**
Expand All @@ -79,9 +84,9 @@ inline auto acos(const Container& x) {
*/
template <typename Container,
require_container_bt<std::is_arithmetic, Container>* = nullptr>
inline auto acos(const Container& x) {
inline auto acos(Container&& x) {
return apply_vector_unary<Container>::apply(
x, [](const auto& v) { return v.array().acos(); });
std::forward<Container>(x), [](auto&& v) { return v.array().acos(); });
}

namespace internal {
Expand Down
17 changes: 9 additions & 8 deletions stan/math/prim/fun/acosh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace math {
* @throw std::domain_error If argument is less than 1.
*/
template <typename T, require_arithmetic_t<T>* = nullptr>
inline double acosh(const T x) {
inline double acosh(T&& x) {
if (is_nan(x)) {
return x;
} else {
Expand All @@ -46,7 +46,7 @@ inline double acosh(const T x) {
* @throw std::domain_error If argument is less than 1.
*/
template <typename T, require_complex_bt<std::is_arithmetic, T>* = nullptr>
inline auto acosh(const T x) {
inline auto acosh(T&& x) {
return std::acosh(x);
}

Expand All @@ -62,8 +62,8 @@ struct acosh_fun {
* @return Inverse hyperbolic cosine of the argument.
*/
template <typename T>
static inline auto fun(const T& x) {
return acosh(x);
static inline auto fun(T&& x) {
return acosh(std::forward<T>(x));
}
};

Expand All @@ -78,8 +78,8 @@ struct acosh_fun {
* @return Elementwise acosh of members of container.
*/
template <typename T, require_ad_container_t<T>* = nullptr>
inline auto acosh(const T& x) {
return apply_scalar_unary<acosh_fun, T>::apply(x);
inline auto acosh(T&& x) {
return apply_scalar_unary<acosh_fun, T>::apply(std::forward<T>(x));
}

/**
Expand All @@ -94,8 +94,9 @@ inline auto acosh(const T& x) {
*/
template <typename Container,
require_container_bt<std::is_arithmetic, Container>* = nullptr>
inline auto acosh(const Container& x) {
return apply_scalar_unary<acosh_fun, Container>::apply(x);
inline auto acosh(Container&& x) {
return apply_scalar_unary<acosh_fun, Container>::apply(
std::forward<Container>(x));
}

namespace internal {
Expand Down
21 changes: 13 additions & 8 deletions stan/math/prim/fun/asin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace math {
* @return arc sine of the argument
*/
template <typename T, require_arithmetic_t<T>* = nullptr>
inline auto asin(const T x) {
inline auto asin(T&& x) {
return std::asin(x);
}

Expand All @@ -36,7 +36,7 @@ inline auto asin(const T x) {
* @return arc sine of the argument
*/
template <typename T, require_complex_bt<std::is_arithmetic, T>* = nullptr>
inline auto asin(const T x) {
inline auto asin(T&& x) {
return std::asin(x);
}

Expand All @@ -49,8 +49,12 @@ inline auto asin(const T x) {
*/
struct asin_fun {
template <typename T>
static inline auto fun(const T& x) {
return asin(x);
static inline auto fun(T&& x) {
if constexpr (std::is_arithmetic_v<std::decay_t<T>>) {
return std::asin(x);
} else {
return asin(std::forward<T>(x));
}
}
};

Expand All @@ -63,8 +67,9 @@ struct asin_fun {
* @return Arcsine of each variable in the container, in radians.
*/
template <typename Container, require_ad_container_t<Container>* = nullptr>
inline auto asin(const Container& x) {
return apply_scalar_unary<asin_fun, Container>::apply(x);
inline auto asin(Container&& x) {
return apply_scalar_unary<asin_fun, Container>::apply(
std::forward<Container>(x));
}

/**
Expand All @@ -77,9 +82,9 @@ inline auto asin(const Container& x) {
*/
template <typename Container,
require_container_bt<std::is_arithmetic, Container>* = nullptr>
inline auto asin(const Container& x) {
inline auto asin(Container&& x) {
return apply_vector_unary<Container>::apply(
x, [](const auto& v) { return v.array().asin(); });
std::forward<Container>(x), [](auto&& v) { return v.array().asin(); });
}

namespace internal {
Expand Down
21 changes: 13 additions & 8 deletions stan/math/prim/fun/asinh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace math {
* @return hyperbolic arc sine of the argument
*/
template <typename T, require_arithmetic_t<T>* = nullptr>
inline auto asinh(const T x) {
inline auto asinh(T&& x) {
return std::asinh(x);
}

Expand All @@ -39,7 +39,7 @@ inline auto asinh(const T x) {
* @return hyperbolic arc sine of the argument
*/
template <typename T, require_complex_bt<std::is_arithmetic, T>* = nullptr>
inline auto asinh(const T x) {
inline auto asinh(T&& x) {
return std::asinh(x);
}

Expand All @@ -52,8 +52,12 @@ inline auto asinh(const T x) {
*/
struct asinh_fun {
template <typename T>
static inline auto fun(const T& x) {
return asinh(x);
static inline auto fun(T&& x) {
if constexpr (std::is_arithmetic_v<std::decay_t<T>>) {
return std::asinh(x);
} else {
return asinh(std::forward<T>(x));
}
}
};

Expand All @@ -66,8 +70,8 @@ struct asinh_fun {
* @return Inverse hyperbolic sine of each value in the container.
*/
template <typename T, require_ad_container_t<T>* = nullptr>
inline auto asinh(const T& x) {
return apply_scalar_unary<asinh_fun, T>::apply(x);
inline auto asinh(T&& x) {
return apply_scalar_unary<asinh_fun, T>::apply(std::forward<T>(x));
}

/**
Expand All @@ -80,8 +84,9 @@ inline auto asinh(const T& x) {
*/
template <typename Container,
require_container_bt<std::is_arithmetic, Container>* = nullptr>
inline auto asinh(const Container& x) {
return apply_scalar_unary<asinh_fun, Container>::apply(x);
inline auto asinh(Container&& x) {
return apply_scalar_unary<asinh_fun, Container>::apply(
std::forward<Container>(x));
}

namespace internal {
Expand Down
Loading