1#ifndef STAN_MATH_REV_FUN_ATAN2_HPP
2#define STAN_MATH_REV_FUN_ATAN2_HPP
30 std::atan2(a.val(), b.val()), [a, b](
const auto& vi)
mutable {
31 double a_sq_plus_b_sq = (a.val() * a.val()) + (b.val() * b.val());
32 a.adj() += vi.adj_ * b.val() / a_sq_plus_b_sq;
33 b.adj() += -vi.adj_ * a.val() / a_sq_plus_b_sq;
51 std::atan2(a.val(), b), [a, b](
const auto& vi)
mutable {
52 double a_sq_plus_b_sq = (a.val() * a.val()) + (b * b);
53 a.adj() += vi.adj_ * b / a_sq_plus_b_sq;
95 std::atan2(a, b.val()), [a, b](
const auto& vi)
mutable {
96 double a_sq_plus_b_sq = (a * a) + (b.val() * b.val());
97 b.adj() += -vi.adj_ * a / a_sq_plus_b_sq;
101template <
typename Mat1,
typename Mat2,
104inline auto atan2(
const Mat1& a,
const Mat2& b) {
108 auto atan2_val =
atan2(arena_a.val(), arena_b.val());
110 =
to_arena((arena_a.val().array() * arena_a.val().array())
111 + (arena_b.val().array() * arena_b.val().array()));
113 atan2(arena_a.val(), arena_b.val()),
114 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
115 arena_a.adj().array()
116 += vi.adj().array() * arena_b.val().array() / a_sq_plus_b_sq;
117 arena_b.adj().array()
118 += -vi.adj().array() * arena_a.val().array() / a_sq_plus_b_sq;
124 =
to_arena((arena_a.val().array() * arena_a.val().array())
125 + (arena_b.array() * arena_b.array()));
128 atan2(arena_a.val(), arena_b),
129 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
130 arena_a.adj().array()
131 += vi.adj().array() * arena_b.array() / a_sq_plus_b_sq;
137 =
to_arena((arena_a.array() * arena_a.array())
138 + (arena_b.val().array() * arena_b.val().array()));
141 atan2(arena_a, arena_b.val()),
142 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
143 arena_b.adj().array()
144 += -vi.adj().array() * arena_a.array() / a_sq_plus_b_sq;
149template <
typename Scalar,
typename VarMat,
152inline auto atan2(
const Scalar& a,
const VarMat& b) {
156 auto atan2_val =
atan2(arena_a.val(), arena_b.val());
158 =
to_arena((arena_a.val() * arena_a.val())
159 + (arena_b.val().array() * arena_b.val().array()));
161 atan2(arena_a.val(), arena_b.val()),
162 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
164 += (vi.adj().array() * arena_b.val().array() / a_sq_plus_b_sq)
166 arena_b.adj().array()
167 += -vi.adj().array() * arena_a.val() / a_sq_plus_b_sq;
172 auto a_sq_plus_b_sq =
to_arena((arena_a.val() * arena_a.val())
173 + (arena_b.array() * arena_b.array()));
176 atan2(arena_a.val(), arena_b),
177 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
179 += (vi.adj().array() * arena_b.array() / a_sq_plus_b_sq).sum();
185 (arena_a * arena_a) + (arena_b.val().array() * arena_b.val().array()));
188 atan2(arena_a, arena_b.val()),
189 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
190 arena_b.adj().array() += -vi.adj().array() * arena_a / a_sq_plus_b_sq;
195template <
typename VarMat,
typename Scalar,
198inline auto atan2(
const VarMat& a,
const Scalar& b) {
202 auto atan2_val =
atan2(arena_a.val(), arena_b.val());
204 =
to_arena((arena_a.val().array() * arena_a.val().array())
205 + (arena_b.val() * arena_b.val()));
207 atan2(arena_a.val(), arena_b.val()),
208 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
209 arena_a.adj().array()
210 += vi.adj().array() * arena_b.val() / a_sq_plus_b_sq;
212 += -(vi.adj().array() * arena_a.val().array() / a_sq_plus_b_sq)
219 (arena_a.val().array() * arena_a.val().array()) + (arena_b * arena_b));
222 atan2(arena_a.val(), arena_b),
223 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
224 arena_a.adj().array() += vi.adj().array() * arena_b / a_sq_plus_b_sq;
229 auto a_sq_plus_b_sq =
to_arena((arena_a.array() * arena_a.array())
230 + (arena_b.val() * arena_b.val()));
233 atan2(arena_a, arena_b.val()),
234 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
236 += -(vi.adj().array() * arena_a.array() / a_sq_plus_b_sq).sum();
require_all_t< is_matrix< std::decay_t< Types > >... > require_all_matrix_t
Require all of the types satisfy is_matrix.
require_t< is_stan_scalar< std::decay_t< T > > > require_stan_scalar_t
Require type satisfies is_stan_scalar.
require_t< is_var_matrix< std::decay_t< T > > > require_var_matrix_t
Require type satisfies is_var_matrix.
require_any_t< is_var_matrix< std::decay_t< Types > >... > require_any_var_matrix_t
Require any of the types satisfy is_var_matrix.
fvar< T > atan2(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.
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...
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 ...