1#ifndef STAN_MATH_REV_FUN_ATAN2_HPP
2#define STAN_MATH_REV_FUN_ATAN2_HPP
29 std::atan2(a.val(), b.val()), [a, b](
const auto& vi)
mutable {
30 double a_sq_plus_b_sq = (a.val() * a.val()) + (b.val() * b.val());
31 a.adj() += vi.adj_ * b.val() / a_sq_plus_b_sq;
32 b.adj() += -vi.adj_ * a.val() / a_sq_plus_b_sq;
50 std::atan2(a.val(), b), [a, b](
const auto& vi)
mutable {
51 double a_sq_plus_b_sq = (a.val() * a.val()) + (b * b);
52 a.adj() += vi.adj_ * b / a_sq_plus_b_sq;
94 std::atan2(a, b.val()), [a, b](
const auto& vi)
mutable {
95 double a_sq_plus_b_sq = (a * a) + (b.val() * b.val());
96 b.adj() += -vi.adj_ * a / a_sq_plus_b_sq;
100template <
typename Mat1,
typename Mat2,
103inline auto atan2(
const Mat1& a,
const Mat2& b) {
107 auto atan2_val =
atan2(arena_a.val(), arena_b.val());
109 =
to_arena((arena_a.val().array() * arena_a.val().array())
110 + (arena_b.val().array() * arena_b.val().array()));
112 atan2(arena_a.val(), arena_b.val()),
113 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
114 arena_a.adj().array()
115 += vi.adj().array() * arena_b.val().array() / a_sq_plus_b_sq;
116 arena_b.adj().array()
117 += -vi.adj().array() * arena_a.val().array() / a_sq_plus_b_sq;
123 =
to_arena((arena_a.val().array() * arena_a.val().array())
124 + (arena_b.array() * arena_b.array()));
127 atan2(arena_a.val(), arena_b),
128 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
129 arena_a.adj().array()
130 += vi.adj().array() * arena_b.array() / a_sq_plus_b_sq;
136 =
to_arena((arena_a.array() * arena_a.array())
137 + (arena_b.val().array() * arena_b.val().array()));
140 atan2(arena_a, arena_b.val()),
141 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
142 arena_b.adj().array()
143 += -vi.adj().array() * arena_a.array() / a_sq_plus_b_sq;
148template <
typename Scalar,
typename VarMat,
151inline auto atan2(
const Scalar& a,
const VarMat& b) {
155 auto atan2_val =
atan2(arena_a.val(), arena_b.val());
157 =
to_arena((arena_a.val() * arena_a.val())
158 + (arena_b.val().array() * arena_b.val().array()));
160 atan2(arena_a.val(), arena_b.val()),
161 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
163 += (vi.adj().array() * arena_b.val().array() / a_sq_plus_b_sq)
165 arena_b.adj().array()
166 += -vi.adj().array() * arena_a.val() / a_sq_plus_b_sq;
171 auto a_sq_plus_b_sq =
to_arena((arena_a.val() * arena_a.val())
172 + (arena_b.array() * arena_b.array()));
175 atan2(arena_a.val(), arena_b),
176 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
178 += (vi.adj().array() * arena_b.array() / a_sq_plus_b_sq).sum();
184 (arena_a * arena_a) + (arena_b.val().array() * arena_b.val().array()));
187 atan2(arena_a, arena_b.val()),
188 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
189 arena_b.adj().array() += -vi.adj().array() * arena_a / a_sq_plus_b_sq;
194template <
typename VarMat,
typename Scalar,
197inline auto atan2(
const VarMat& a,
const Scalar& b) {
201 auto atan2_val =
atan2(arena_a.val(), arena_b.val());
203 =
to_arena((arena_a.val().array() * arena_a.val().array())
204 + (arena_b.val() * arena_b.val()));
206 atan2(arena_a.val(), arena_b.val()),
207 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
208 arena_a.adj().array()
209 += vi.adj().array() * arena_b.val() / a_sq_plus_b_sq;
211 += -(vi.adj().array() * arena_a.val().array() / a_sq_plus_b_sq)
218 (arena_a.val().array() * arena_a.val().array()) + (arena_b * arena_b));
221 atan2(arena_a.val(), arena_b),
222 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
223 arena_a.adj().array() += vi.adj().array() * arena_b / a_sq_plus_b_sq;
228 auto a_sq_plus_b_sq =
to_arena((arena_a.array() * arena_a.array())
229 + (arena_b.val() * arena_b.val()));
232 atan2(arena_a, arena_b.val()),
233 [arena_a, arena_b, a_sq_plus_b_sq](
auto& vi)
mutable {
235 += -(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 ...