Automatic Differentiation
 
Loading...
Searching...
No Matches
von_mises_cdf.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_PROB_VON_MISES_CDF_HPP
2#define STAN_MATH_PRIM_PROB_VON_MISES_CDF_HPP
3
6#include <cmath>
7
8namespace stan {
9namespace math {
10
11namespace internal {
12
22template <typename T_x, typename T_k>
24 const T_k& k) {
25 const double pi = stan::math::pi();
26 int p = value_of_rec(28 + 0.5 * k - 100 / (k + 5) + 1);
27 auto s = sin(x);
28 auto c = cos(x);
29 auto sn = sin(p * x);
30 auto cn = cos(p * x);
31
32 using return_t = return_type_t<T_x, T_k>;
33 return_t R = 0.0;
34 return_t V = 0.0;
35
36 int n;
37 for (n = 1; n < p; n++) {
38 auto sn_tmp = sn * c - cn * s;
39 cn = cn * c + sn * s;
40 sn = sn_tmp;
41 R = 1 / (2.0 * (p - n) / k + R);
42 V = R * (sn / (p - n) + V);
43 }
44 return 0.5 + x / TWO_PI + V / pi;
45}
46
52template <typename T_x, typename T_k>
54 const T_k& k) {
55 using std::exp;
56 using std::sqrt;
57
58 const auto b = sqrt(2 / pi()) * exp(k) / modified_bessel_first_kind(0, k);
59 const auto z = b * sin(x / 2);
60 const double mu = 0;
61 const double sigma = 1;
62
63 return normal_cdf(z, mu, sigma);
64}
65
72template <typename T_x, typename T_k>
74 const T_k& k) {
75 using return_t = return_type_t<T_x, T_k>;
76 return_t f;
77 if (k < 49) {
78 f = von_mises_cdf_series(x, k);
79 if (f < 0) {
80 f = 0.0;
81 return f;
82 }
83 if (f > 1) {
84 f = 1.0;
85 return f;
86 }
87 return f;
88 } else if (k < 50) {
89 f = (50.0 - k) * von_mises_cdf_series(x, 49.0)
90 + (k - 49.0) * von_mises_cdf_normalapprox(x, 50.0);
91 return f;
92 } else {
94 return f;
95 }
96}
97
98} // namespace internal
99
120template <typename T_x, typename T_mu, typename T_k>
121inline return_type_t<T_x, T_mu, T_k> von_mises_cdf(const T_x& x, const T_mu& mu,
122 const T_k& k) {
124 const double pi = stan::math::pi();
125
126 using T_return = return_type_t<T_x, T_mu, T_k>;
127 using T_x_ref = ref_type_t<T_x>;
128 using T_mu_ref = ref_type_t<T_mu>;
129 using T_k_ref = ref_type_t<T_k>;
130 static char const* function = "von_mises_cdf";
131 check_consistent_sizes(function, "Random variable", x, "Location parameter",
132 mu, "Scale parameter", k);
133
134 T_x_ref x_ref = x;
135 T_mu_ref mu_ref = mu;
136 T_k_ref k_ref = k;
137
138 check_bounded(function, "Random variable", value_of(x_ref), -pi, pi);
139 check_finite(function, "Location parameter", value_of(mu_ref));
140 check_positive(function, "Scale parameter", value_of(k_ref));
141
142 if (size_zero(x, mu, k)) {
143 return 1.0;
144 }
145
146 T_return res(1.0);
147
148 scalar_seq_view<T_x_ref> x_vec(x_ref);
149 scalar_seq_view<T_mu_ref> mu_vec(mu_ref);
150 scalar_seq_view<T_k_ref> k_vec(k_ref);
151 size_t N = max_size(x, mu, k);
152
153 for (size_t n = 0; n < N; ++n) {
154 auto x_n = x_vec[n];
155 auto mu_n = mu_vec[n];
156 auto k_n = k_vec[n];
157
158 if (x_n == -pi) {
159 res *= 0.0;
160 } else if (x_n == pi) {
161 res *= 1.0;
162 } else {
163 // shift x so that mean is 0
164 T_return x2 = x_n - mu_n;
165
166 // x2 is on an interval (2*n*pi, (2*n + 1)*pi), move it to (-pi, pi)
167 x2 += pi;
168 const auto x_floor = floor(x2 / TWO_PI);
169 const auto x_modded = x2 - x_floor * TWO_PI;
170 x2 = x_modded - pi;
171
172 // mu is on an interval (2*n*pi, (2*n + 1)*pi), move it to (-pi, pi)
173 T_return mu2 = mu_n + pi;
174 const auto mu_floor = floor(mu2 / TWO_PI);
175 const auto mu_modded = mu2 - mu_floor * TWO_PI;
176 mu2 = mu_modded - pi;
177
178 // find cut
179 T_return cut, bound_val;
180 if (mu2 < 0) {
181 cut = mu2 + pi;
182 bound_val = -pi - mu2;
183 }
184 if (mu2 >= 0) {
185 cut = mu2 - pi;
186 bound_val = pi - mu2;
187 }
188
189 T_return f_bound_val = von_mises_cdf_centered(bound_val, k_n);
190 T_return cdf_n;
191 if (x_n <= cut) {
192 cdf_n = von_mises_cdf_centered(x2, k_n) - f_bound_val;
193 } else {
194 cdf_n = von_mises_cdf_centered(x2, k_n) + 1 - f_bound_val;
195 }
196
197 if (cdf_n < 0.0)
198 cdf_n = 0.0;
199
200 res *= cdf_n;
201 }
202 }
203
204 return res;
205}
206
207} // namespace math
208} // namespace stan
209
210#endif
scalar_seq_view provides a uniform sequence-like wrapper around either a scalar or a sequence of scal...
return_type_t< T_y_cl, T_loc_cl, T_scale_cl > normal_cdf(const T_y_cl &y, const T_loc_cl &mu, const T_scale_cl &sigma)
Returns the normal cumulative distribution function for the given location, and scale.
return_type_t< T_x, T_mu, T_k > von_mises_cdf(const T_x &x, const T_mu &mu, const T_k &k)
Calculates the cumulative distribution function of the von Mises distribution:
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
return_type_t< T_x, T_k > von_mises_cdf_normalapprox(const T_x &x, const T_k &k)
conv_mises_cdf_normapprox(x, k) is used to approximate the von Mises cdf for k > 50.
return_type_t< T_x, T_k > von_mises_cdf_series(const T_x &x, const T_k &k)
This implementation of the von Mises cdf is a copy of scipy's.
return_type_t< T_x, T_k > von_mises_cdf_centered(const T_x &x, const T_k &k)
This function calculates the cdf of the von Mises distribution in the case where the distribution has...
double value_of_rec(const fvar< T > &v)
Return the value of the specified variable.
fvar< T > sin(const fvar< T > &x)
Definition sin.hpp:16
bool size_zero(const T &x)
Returns 1 if input is of length 0, returns 0 otherwise.
Definition size_zero.hpp:19
void check_bounded(const char *function, const char *name, const T_y &y, const T_low &low, const T_high &high)
Check if the value is between the low and high values, inclusively.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
fvar< T > modified_bessel_first_kind(int v, const fvar< T > &z)
void check_consistent_sizes(const char *)
Trivial no input case, this function is a no-op.
fvar< T > sqrt(const fvar< T > &x)
Definition sqrt.hpp:18
void check_finite(const char *function, const char *name, const T_y &y)
Return true if all values in y are finite.
fvar< T > floor(const fvar< T > &x)
Definition floor.hpp:13
fvar< T > cos(const fvar< T > &x)
Definition cos.hpp:16
static constexpr double TWO_PI
Twice the value of , .
Definition constants.hpp:62
void check_positive(const char *function, const char *name, const T_y &y)
Check if y is positive.
static constexpr double pi()
Return the value of pi.
Definition constants.hpp:36
int64_t max_size(const T1 &x1, const Ts &... xs)
Calculate the size of the largest input.
Definition max_size.hpp:20
fvar< T > exp(const fvar< T > &x)
Definition exp.hpp:15
typename ref_type_if< true, T >::type ref_type_t
Definition ref_type.hpp:56
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...