Automatic Differentiation
 
Loading...
Searching...
No Matches
atan2.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_REV_FUN_ATAN2_HPP
2#define STAN_MATH_REV_FUN_ATAN2_HPP
3
7#include <cmath>
8
9namespace stan {
10namespace math {
11
28inline var atan2(const var& a, const var& b) {
29 return make_callback_var(
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;
34 });
35}
36
49inline var atan2(const var& a, double b) {
50 return make_callback_var(
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;
54 });
55}
56
93inline var atan2(double a, const var& b) {
94 return make_callback_var(
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;
98 });
99}
100
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());
109 auto a_sq_plus_b_sq
110 = to_arena((arena_a.val().array() * arena_a.val().array())
111 + (arena_b.val().array() * arena_b.val().array()));
112 return make_callback_var(
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;
119 });
120 } else if (!is_constant<Mat1>::value) {
123 auto a_sq_plus_b_sq
124 = to_arena((arena_a.val().array() * arena_a.val().array())
125 + (arena_b.array() * arena_b.array()));
126
127 return make_callback_var(
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;
132 });
133 } else if (!is_constant<Mat2>::value) {
136 auto a_sq_plus_b_sq
137 = to_arena((arena_a.array() * arena_a.array())
138 + (arena_b.val().array() * arena_b.val().array()));
139
140 return make_callback_var(
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;
145 });
146 }
147}
148
149template <typename Scalar, typename VarMat,
152inline auto atan2(const Scalar& a, const VarMat& b) {
154 var arena_a = a;
156 auto atan2_val = atan2(arena_a.val(), arena_b.val());
157 auto a_sq_plus_b_sq
158 = to_arena((arena_a.val() * arena_a.val())
159 + (arena_b.val().array() * arena_b.val().array()));
160 return make_callback_var(
161 atan2(arena_a.val(), arena_b.val()),
162 [arena_a, arena_b, a_sq_plus_b_sq](auto& vi) mutable {
163 arena_a.adj()
164 += (vi.adj().array() * arena_b.val().array() / a_sq_plus_b_sq)
165 .sum();
166 arena_b.adj().array()
167 += -vi.adj().array() * arena_a.val() / a_sq_plus_b_sq;
168 });
169 } else if (!is_constant<Scalar>::value) {
170 var arena_a = a;
172 auto a_sq_plus_b_sq = to_arena((arena_a.val() * arena_a.val())
173 + (arena_b.array() * arena_b.array()));
174
175 return make_callback_var(
176 atan2(arena_a.val(), arena_b),
177 [arena_a, arena_b, a_sq_plus_b_sq](auto& vi) mutable {
178 arena_a.adj()
179 += (vi.adj().array() * arena_b.array() / a_sq_plus_b_sq).sum();
180 });
181 } else if (!is_constant<VarMat>::value) {
182 double arena_a = value_of(a);
184 auto a_sq_plus_b_sq = to_arena(
185 (arena_a * arena_a) + (arena_b.val().array() * arena_b.val().array()));
186
187 return make_callback_var(
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;
191 });
192 }
193}
194
195template <typename VarMat, typename Scalar,
198inline auto atan2(const VarMat& a, const Scalar& b) {
201 var arena_b = b;
202 auto atan2_val = atan2(arena_a.val(), arena_b.val());
203 auto a_sq_plus_b_sq
204 = to_arena((arena_a.val().array() * arena_a.val().array())
205 + (arena_b.val() * arena_b.val()));
206 return make_callback_var(
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;
211 arena_b.adj()
212 += -(vi.adj().array() * arena_a.val().array() / a_sq_plus_b_sq)
213 .sum();
214 });
215 } else if (!is_constant<VarMat>::value) {
217 double arena_b = value_of(b);
218 auto a_sq_plus_b_sq = to_arena(
219 (arena_a.val().array() * arena_a.val().array()) + (arena_b * arena_b));
220
221 return make_callback_var(
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;
225 });
226 } else if (!is_constant<Scalar>::value) {
228 var arena_b = b;
229 auto a_sq_plus_b_sq = to_arena((arena_a.array() * arena_a.array())
230 + (arena_b.val() * arena_b.val()));
231
232 return make_callback_var(
233 atan2(arena_a, arena_b.val()),
234 [arena_a, arena_b, a_sq_plus_b_sq](auto& vi) mutable {
235 arena_b.adj()
236 += -(vi.adj().array() * arena_a.array() / a_sq_plus_b_sq).sum();
237 });
238 }
239}
240
241} // namespace math
242} // namespace stan
243#endif
require_all_t< is_matrix< std::decay_t< Types > >... > require_all_matrix_t
Require all of the types satisfy is_matrix.
Definition is_matrix.hpp:38
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)
Definition atan2.hpp:14
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.
Definition value_of.hpp:18
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...
Definition to_arena.hpp:25
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 ...