1#ifndef STAN_MATH_REV_FUN_MULTIPLY_LOG_HPP
2#define STAN_MATH_REV_FUN_MULTIPLY_LOG_HPP
101template <
typename T1,
typename T2, require_all_matrix_t<T1, T2>* =
nullptr,
102 require_any_var_matrix_t<T1, T2>* =
nullptr>
111 [arena_a, arena_b](
const auto& res)
mutable {
112 arena_a.adj().array()
113 += res.adj().array() * arena_b.val().array().log();
114 arena_b.adj().array() += res.adj().array() * arena_a.val().array()
115 / arena_b.val().array();
117 }
else if (!is_constant<T1>::value) {
118 arena_t<promote_scalar_t<var, T1>> arena_a = a;
119 arena_t<promote_scalar_t<double, T2>> arena_b =
value_of(b);
122 [arena_a, arena_b](
const auto& res)
mutable {
123 arena_a.adj().array()
125 * arena_b.val().array().log();
128 arena_t<promote_scalar_t<double, T1>> arena_a =
value_of(a);
129 arena_t<promote_scalar_t<var, T2>> arena_b = b;
132 [arena_a, arena_b](
const auto& res)
mutable {
133 arena_b.adj().array() += res.adj().array()
134 * arena_a.val().array()
135 / arena_b.val().array();
149template <
typename T1,
typename T2, require_var_matrix_t<T1>* =
nullptr,
150 require_stan_scalar_t<T2>* =
nullptr>
154 if (!is_constant<T1>::value && !is_constant<T2>::value) {
155 arena_t<promote_scalar_t<var, T1>> arena_a = a;
160 [arena_a, arena_b](
const auto& res)
mutable {
161 arena_a.adj().array() += res.adj().array() * log(arena_b.val());
162 arena_b.adj() += (res.adj().array() * arena_a.val().array()).sum()
165 }
else if (!is_constant<T1>::value) {
166 arena_t<promote_scalar_t<var, T1>> arena_a = a;
169 [arena_a, b](
const auto& res)
mutable {
170 arena_a.adj().array()
174 arena_t<promote_scalar_t<double, T1>> arena_a =
value_of(a);
179 [arena_a, arena_b](
const auto& res)
mutable {
181 += (res.adj().array() * arena_a.array()).sum() / arena_b.val();
195template <
typename T1,
typename T2, require_stan_scalar_t<T1>* =
nullptr,
196 require_var_matrix_t<T2>* =
nullptr>
198 if (!is_constant<T1>::value && !is_constant<T2>::value) {
200 arena_t<promote_scalar_t<var, T2>> arena_b = b;
204 [arena_a, arena_b](
const auto& res)
mutable {
206 += (res.adj().array() * arena_b.val().array().log()).sum();
207 arena_b.adj().array()
208 += arena_a.val() * res.adj().array() / arena_b.val().array();
210 }
else if (!is_constant<T1>::value) {
212 arena_t<promote_scalar_t<double, T2>> arena_b =
value_of(b);
216 [arena_a, arena_b](
const auto& res)
mutable {
218 += (res.adj().array() * arena_b.val().array().log()).sum();
221 arena_t<promote_scalar_t<var, T2>> arena_b = b;
224 [a, arena_b](
const auto& res)
mutable {
225 arena_b.adj().array() += value_of(a)
227 / arena_b.val().array();
multiply_log_dv_vari(double a, vari *bvi)
multiply_log_vd_vari(vari *avi, double b)
multiply_log_vv_vari(vari *avi, vari *bvi)
fvar< T > multiply_log(const fvar< T > &x1, const fvar< T > &x2)
var_value< plain_type_t< T > > make_callback_var(T &&value, F &&functor)
Creates a new var initialized with a callback_vari with a given value and reverse-pass callback funct...
T value_of(const fvar< T > &v)
Return the value of the specified variable.
fvar< T > log(const fvar< T > &x)
void check_matching_dims(const char *function, const char *name1, const T1 &y1, const char *name2, const T2 &y2)
Check if the two containers have the same dimensions.
typename internal::arena_type_impl< std::decay_t< T > >::type arena_t
Determines a type that can be used in place of T that does any dynamic allocations on the AD stack.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Metaprogramming struct to detect whether a given type is constant in the mathematical sense (not the ...