1 #ifndef STAN_MATH_PRIM_PROB_CAUCHY_LCCDF_HPP
2 #define STAN_MATH_PRIM_PROB_CAUCHY_LCCDF_HPP
3
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/err.hpp>
6 #include <stan/math/prim/fun/constants.hpp>
7 #include <stan/math/prim/fun/log.hpp>
8 #include <stan/math/prim/fun/max_size.hpp>
9 #include <stan/math/prim/fun/scalar_seq_view.hpp>
10 #include <stan/math/prim/fun/size_zero.hpp>
11 #include <stan/math/prim/fun/value_of.hpp>
12 #include <stan/math/prim/functor/operands_and_partials.hpp>
13 #include <cmath>
14
15 namespace stan {
16 namespace math {
17
18 /** \ingroup prob_dists
19 * Returns the cauchy log complementary cumulative distribution function
20 * for the given location, and scale. If given containers of matching sizes
21 * returns the log sum of probabilities.
22 *
23 * @tparam T_y type of real parameter
24 * @tparam T_loc type of location parameter
25 * @tparam T_scale type of scale parameter
26 * @param y real parameter
27 * @param mu location parameter
28 * @param sigma scale parameter
29 * @return log probability or log sum of probabilities
30 * @throw std::domain_error if sigma is nonpositive or y, mu are nan
31 * @throw std::invalid_argument if container sizes mismatch
32 */
33 template <typename T_y, typename T_loc, typename T_scale,
34 require_all_not_nonscalar_prim_or_rev_kernel_expression_t<
35 T_y, T_loc, T_scale>* = nullptr>
cauchy_lccdf(const T_y & y,const T_loc & mu,const T_scale & sigma)36 return_type_t<T_y, T_loc, T_scale> cauchy_lccdf(const T_y& y, const T_loc& mu,
37 const T_scale& sigma) {
38 using T_partials_return = partials_return_t<T_y, T_loc, T_scale>;
39 using std::atan;
40 using std::log;
41 using T_y_ref = ref_type_t<T_y>;
42 using T_mu_ref = ref_type_t<T_loc>;
43 using T_sigma_ref = ref_type_t<T_scale>;
44 static const char* function = "cauchy_lccdf";
45 check_consistent_sizes(function, "Random variable", y, "Location parameter",
46 mu, "Scale Parameter", sigma);
47 T_y_ref y_ref = y;
48 T_mu_ref mu_ref = mu;
49 T_sigma_ref sigma_ref = sigma;
50 check_not_nan(function, "Random variable", y_ref);
51 check_finite(function, "Location parameter", mu_ref);
52 check_positive_finite(function, "Scale parameter", sigma_ref);
53
54 if (size_zero(y, mu, sigma)) {
55 return 0;
56 }
57
58 T_partials_return ccdf_log(0.0);
59 operands_and_partials<T_y_ref, T_mu_ref, T_sigma_ref> ops_partials(
60 y_ref, mu_ref, sigma_ref);
61
62 scalar_seq_view<T_y_ref> y_vec(y_ref);
63 scalar_seq_view<T_mu_ref> mu_vec(mu_ref);
64 scalar_seq_view<T_sigma_ref> sigma_vec(sigma_ref);
65 size_t N = max_size(y, mu, sigma);
66
67 for (size_t n = 0; n < N; n++) {
68 const T_partials_return y_dbl = y_vec.val(n);
69 const T_partials_return mu_dbl = mu_vec.val(n);
70 const T_partials_return sigma_inv_dbl = 1.0 / sigma_vec.val(n);
71 const T_partials_return sigma_dbl = sigma_vec.val(n);
72 const T_partials_return z = (y_dbl - mu_dbl) * sigma_inv_dbl;
73
74 const T_partials_return Pn = 0.5 - atan(z) / pi();
75 ccdf_log += log(Pn);
76
77 const T_partials_return rep_deriv
78 = 1.0 / (Pn * pi() * (z * z * sigma_dbl + sigma_dbl));
79 if (!is_constant_all<T_y>::value) {
80 ops_partials.edge1_.partials_[n] -= rep_deriv;
81 }
82 if (!is_constant_all<T_loc>::value) {
83 ops_partials.edge2_.partials_[n] += rep_deriv;
84 }
85 if (!is_constant_all<T_scale>::value) {
86 ops_partials.edge3_.partials_[n] += rep_deriv * z;
87 }
88 }
89 return ops_partials.build(ccdf_log);
90 }
91
92 } // namespace math
93 } // namespace stan
94 #endif
95