1 #ifndef STAN_MATH_OPENCL_PRIM_BERNOULLI_CDF_HPP
2 #define STAN_MATH_OPENCL_PRIM_BERNOULLI_CDF_HPP
3 #ifdef STAN_OPENCL
4 
5 #include <stan/math/prim/meta.hpp>
6 #include <stan/math/prim/err.hpp>
7 #include <stan/math/opencl/kernel_generator.hpp>
8 #include <stan/math/prim/fun/constants.hpp>
9 #include <stan/math/prim/functor/operands_and_partials.hpp>
10 
11 namespace stan {
12 namespace math {
13 
14 /** \ingroup prob_dists
15  * Returns the CDF of the Bernoulli distribution. If containers are
16  * supplied, returns the product of the probabilities.
17  *
18  * @tparam T_n_cl type of integer parameter
19  * @tparam T_prob_cl type of chance of success parameter
20  * @param n integer parameter
21  * @param theta logit-transformed chance of success parameter
22  * @return log probability or log sum of probabilities
23  * @throw std::domain_error if theta is not a valid probability
24  * @throw std::invalid_argument if container sizes mismatch.
25  */
26 template <
27     typename T_n_cl, typename T_prob_cl,
28     require_all_prim_or_rev_kernel_expression_t<T_n_cl, T_prob_cl>* = nullptr,
29     require_any_not_stan_scalar_t<T_n_cl, T_prob_cl>* = nullptr>
bernoulli_cdf(const T_n_cl & n,const T_prob_cl & theta)30 return_type_t<T_prob_cl> bernoulli_cdf(const T_n_cl& n,
31                                        const T_prob_cl& theta) {
32   static const char* function = "bernoulli_cdf(OpenCL)";
33   using T_partials_return = partials_return_t<T_prob_cl>;
34   using std::isnan;
35   constexpr bool is_n_vector = !is_stan_scalar<T_n_cl>::value;
36   constexpr bool is_theta_vector = !is_stan_scalar<T_prob_cl>::value;
37 
38   check_consistent_sizes(function, "Random variable", n,
39                          "Probability parameter", theta);
40   const size_t N = is_n_vector ? size(n) : size(theta);
41   if (N == 0) {
42     return 1.0;
43   }
44 
45   const auto& theta_col = as_column_vector_or_scalar(theta);
46   const auto& theta_val = value_of(theta_col);
47 
48   auto check_theta_bounded = check_cl(function, "Probability parameter",
49                                       theta_val, "in the interval [0, 1]");
50   auto theta_bounded_expr = 0.0 <= theta_val && theta_val <= 1.0;
51 
52   auto any_n_negative = colwise_max(cast<char>(n < 0));
53   auto cond = n >= 1;
54   auto Pi_uncond = 1.0 - theta_val;
55   auto Pi = select(cond, INFTY, Pi_uncond);
56   auto P_expr = colwise_prod(select(cond, 1.0, Pi_uncond));
57 
58   matrix_cl<char> any_n_negative_cl;
59   matrix_cl<double> Pi_cl;
60   matrix_cl<double> P_cl;
61 
62   results(check_theta_bounded, any_n_negative_cl, Pi_cl, P_cl)
63       = expressions(theta_bounded_expr, any_n_negative,
64                     calc_if<(!is_constant_all<T_prob_cl>::value)>(Pi), P_expr);
65 
66   if (from_matrix_cl(any_n_negative_cl).maxCoeff()) {
67     return 0.0;
68   }
69 
70   T_partials_return P = from_matrix_cl(P_cl).prod();
71   operands_and_partials<decltype(theta_col)> ops_partials(theta_col);
72 
73   if (!is_constant_all<T_prob_cl>::value) {
74     ops_partials.edge1_.partials_ = elt_divide(-P, Pi_cl);
75   }
76 
77   return ops_partials.build(P);
78 }
79 
80 }  // namespace math
81 }  // namespace stan
82 #endif
83 #endif
84