1#ifndef STAN_MATH_REV_CORE_OPERATOR_DIVISION_HPP
2#define STAN_MATH_REV_CORE_OPERATOR_DIVISION_HPP
63 dividend.val() / divisor.val(), [dividend, divisor](
auto&& vi) {
64 dividend.adj() += vi.adj() / divisor.val();
66 -= vi.adj() * dividend.val() / (divisor.val() * divisor.val());
83template <
typename Arith, require_arithmetic_t<Arith>* =
nullptr>
89 dividend.val() / divisor,
90 [dividend, divisor](
auto&& vi) { dividend.adj() += vi.adj() / divisor; });
105template <
typename Arith, require_arithmetic_t<Arith>* =
nullptr>
108 dividend / divisor.val(), [dividend, divisor](
auto&& vi) {
109 divisor.adj() -= vi.adj() * dividend / (divisor.val() * divisor.val());
122template <
typename Scalar,
typename Mat, require_matrix_t<Mat>* =
nullptr,
123 require_stan_scalar_t<Scalar>* =
nullptr,
124 require_all_st_var_or_arithmetic<Scalar, Mat>* =
nullptr,
125 require_any_st_var<Scalar, Mat>* =
nullptr>
126inline auto divide(
const Mat& m, Scalar c) {
130 auto inv_c = (1.0 / arena_c.val());
133 auto inv_times_adj = (inv_c * res.adj().array()).eval();
134 arena_c.adj() -= (inv_times_adj * res.val().array()).
sum();
135 arena_m.adj().array() += inv_times_adj;
143 arena_m.adj().array() += inv_c * res.adj_op().array();
148 auto inv_c = (1.0 / arena_c.val());
151 arena_c.adj() -= inv_c * (res.adj().array() * res.val().array()).sum();
166template <
typename Scalar,
typename Mat, require_matrix_t<Mat>* =
nullptr,
167 require_stan_scalar_t<Scalar>* =
nullptr,
168 require_all_st_var_or_arithmetic<Scalar, Mat>* =
nullptr,
169 require_any_st_var<Scalar, Mat>* =
nullptr>
170inline auto divide(Scalar c,
const Mat& m) {
173 auto inv_m =
to_arena(arena_m.val().array().inverse());
177 auto inv_times_res = (inv_m * res.adj().array()).eval();
178 arena_m.adj().array() -= inv_times_res * res.val().array();
179 arena_c.adj() += (inv_times_res).
sum();
184 auto inv_m =
to_arena(arena_m.val().array().inverse());
187 arena_m.adj().array() -= inv_m * res.adj().array() * res.val().array();
195 arena_c.adj() += (inv_m * res.adj().array()).sum();
212template <
typename Mat1,
typename Mat2,
215inline auto divide(
const Mat1& m1,
const Mat2& m2) {
219 auto inv_m2 =
to_arena(arena_m2.val().array().inverse());
220 using val_ret =
decltype((inv_m2 * arena_m1.val().array()).matrix().eval());
224 auto inv_times_res = (inv_m2 * res.adj().array()).eval();
225 arena_m1.adj().array() += inv_times_res;
226 arena_m2.adj().array() -= inv_times_res * res.val().array();
228 return ret_type(res);
232 auto inv_m2 =
to_arena(arena_m2.val().array().inverse());
233 using val_ret =
decltype((inv_m2 * arena_m1.array()).matrix().eval());
237 arena_m2.adj().array() -= inv_m2 * res.adj().array() * res.val().array();
239 return ret_type(res);
243 auto inv_m2 =
to_arena(arena_m2.array().inverse());
244 using val_ret =
decltype((inv_m2 * arena_m1.val().array()).matrix().eval());
248 arena_m1.adj().array() += inv_m2 * res.adj().array();
250 return ret_type(res);
254template <
typename T1,
typename T2, require_any_var_matrix_t<T1, T2>* =
nullptr>
255inline auto operator/(
const T1& dividend,
const T2& divisor) {
256 return divide(dividend, divisor);
259inline std::complex<var>
operator/(
const std::complex<var>& x1,
260 const std::complex<var>& x2) {
require_any_t< container_type_check_base< is_matrix, scalar_type_t, TypeCheck, Check >... > require_any_matrix_st
Require any of the types satisfy is_matrix.
require_all_t< container_type_check_base< is_matrix, scalar_type_t, TypeCheck, Check >... > require_all_matrix_st
Require all of the types does not satisfy is_matrix.
auto divide(T_a &&a, double d)
Returns the elementwise division of the kernel generator expression.
complex_return_t< U, V > complex_divide(const U &lhs, const V &rhs)
Return the quotient of the specified arguments.
fvar< T > operator/(const fvar< T > &x1, const fvar< T > &x2)
Return the result of dividing the first argument by the second.
typename promote_scalar_type< std::decay_t< T >, std::decay_t< S > >::type promote_scalar_t
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...
void reverse_pass_callback(F &&functor)
Puts a callback on the autodiff stack to be called in reverse pass.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
arena_t< T > to_arena(const T &a)
Converts given argument into a type that either has any dynamic allocation on AD stack or schedules i...
Eigen::Matrix< value_type_t< EigMat >, EigMat::RowsAtCompileTime, EigMat::ColsAtCompileTime > inverse(const EigMat &m)
Forward mode specialization of calculating the inverse of the matrix.
auto sum(const std::vector< T > &m)
Return the sum of the entries of the specified standard vector.
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.
std::conditional_t< is_any_var_matrix< ReturnType, Types... >::value, stan::math::var_value< stan::math::promote_scalar_t< double, plain_type_t< ReturnType > > >, stan::math::promote_scalar_t< stan::math::var_value< double >, plain_type_t< ReturnType > > > return_var_matrix_t
Given an Eigen type and several inputs, determine if a matrix should be var<Matrix> or Matrix<var>.
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 ...