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
6#include <cmath>
7
8namespace stan {
9namespace math {
10
27inline var atan2(const var& a, const var& b) {
28 return make_callback_var(
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;
33 });
34}
35
48inline var atan2(const var& a, double b) {
49 return make_callback_var(
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;
53 });
54}
55
92inline var atan2(double a, const var& b) {
93 return make_callback_var(
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;
97 });
98}
99
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());
108 auto a_sq_plus_b_sq
109 = to_arena((arena_a.val().array() * arena_a.val().array())
110 + (arena_b.val().array() * arena_b.val().array()));
111 return make_callback_var(
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;
118 });
119 } else if (!is_constant<Mat1>::value) {
122 auto a_sq_plus_b_sq
123 = to_arena((arena_a.val().array() * arena_a.val().array())
124 + (arena_b.array() * arena_b.array()));
125
126 return make_callback_var(
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;
131 });
132 } else if (!is_constant<Mat2>::value) {
135 auto a_sq_plus_b_sq
136 = to_arena((arena_a.array() * arena_a.array())
137 + (arena_b.val().array() * arena_b.val().array()));
138
139 return make_callback_var(
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;
144 });
145 }
146}
147
148template <typename Scalar, typename VarMat,
151inline auto atan2(const Scalar& a, const VarMat& b) {
153 var arena_a = a;
155 auto atan2_val = atan2(arena_a.val(), arena_b.val());
156 auto a_sq_plus_b_sq
157 = to_arena((arena_a.val() * arena_a.val())
158 + (arena_b.val().array() * arena_b.val().array()));
159 return make_callback_var(
160 atan2(arena_a.val(), arena_b.val()),
161 [arena_a, arena_b, a_sq_plus_b_sq](auto& vi) mutable {
162 arena_a.adj()
163 += (vi.adj().array() * arena_b.val().array() / a_sq_plus_b_sq)
164 .sum();
165 arena_b.adj().array()
166 += -vi.adj().array() * arena_a.val() / a_sq_plus_b_sq;
167 });
168 } else if (!is_constant<Scalar>::value) {
169 var arena_a = a;
171 auto a_sq_plus_b_sq = to_arena((arena_a.val() * arena_a.val())
172 + (arena_b.array() * arena_b.array()));
173
174 return make_callback_var(
175 atan2(arena_a.val(), arena_b),
176 [arena_a, arena_b, a_sq_plus_b_sq](auto& vi) mutable {
177 arena_a.adj()
178 += (vi.adj().array() * arena_b.array() / a_sq_plus_b_sq).sum();
179 });
180 } else if (!is_constant<VarMat>::value) {
181 double arena_a = value_of(a);
183 auto a_sq_plus_b_sq = to_arena(
184 (arena_a * arena_a) + (arena_b.val().array() * arena_b.val().array()));
185
186 return make_callback_var(
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;
190 });
191 }
192}
193
194template <typename VarMat, typename Scalar,
197inline auto atan2(const VarMat& a, const Scalar& b) {
200 var arena_b = b;
201 auto atan2_val = atan2(arena_a.val(), arena_b.val());
202 auto a_sq_plus_b_sq
203 = to_arena((arena_a.val().array() * arena_a.val().array())
204 + (arena_b.val() * arena_b.val()));
205 return make_callback_var(
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;
210 arena_b.adj()
211 += -(vi.adj().array() * arena_a.val().array() / a_sq_plus_b_sq)
212 .sum();
213 });
214 } else if (!is_constant<VarMat>::value) {
216 double arena_b = value_of(b);
217 auto a_sq_plus_b_sq = to_arena(
218 (arena_a.val().array() * arena_a.val().array()) + (arena_b * arena_b));
219
220 return make_callback_var(
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;
224 });
225 } else if (!is_constant<Scalar>::value) {
227 var arena_b = b;
228 auto a_sq_plus_b_sq = to_arena((arena_a.array() * arena_a.array())
229 + (arena_b.val() * arena_b.val()));
230
231 return make_callback_var(
232 atan2(arena_a, arena_b.val()),
233 [arena_a, arena_b, a_sq_plus_b_sq](auto& vi) mutable {
234 arena_b.adj()
235 += -(vi.adj().array() * arena_a.array() / a_sq_plus_b_sq).sum();
236 });
237 }
238}
239
240} // namespace math
241} // namespace stan
242#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:13
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 ...