1#ifndef STAN_MATH_PRIM_PROB_NORMAL_LCDF_HPP
2#define STAN_MATH_PRIM_PROB_NORMAL_LCDF_HPP
24template <
typename T_y,
typename T_loc,
typename T_scale,
26 T_y, T_loc, T_scale>* =
nullptr>
29 const T_scale& sigma) {
39 static constexpr const char* function =
"normal_lcdf";
41 mu,
"Scale parameter", sigma);
44 T_sigma_ref sigma_ref = sigma;
53 T_partials_return cdf_log(0.0);
61 for (
size_t n = 0; n < N; n++) {
62 const T_partials_return y_dbl = y_vec.val(n);
63 const T_partials_return mu_dbl = mu_vec.val(n);
64 const T_partials_return sigma_dbl = sigma_vec.val(n);
66 const T_partials_return scaled_diff
67 = (y_dbl - mu_dbl) / (sigma_dbl *
SQRT_TWO);
69 const T_partials_return sigma_sqrt2 = sigma_dbl *
SQRT_TWO;
70 const T_partials_return x2 =
square(scaled_diff);
79 if (scaled_diff > 0.0) {
81 cdf_log +=
log1p(-0.5 *
erfc(scaled_diff));
85 }
else if (scaled_diff > -20.0) {
88 }
else if (10.0 *
log(
fabs(scaled_diff))
89 <
log(std::numeric_limits<T_partials_return>::max())) {
94 const T_partials_return x4 =
pow(scaled_diff, 4);
95 const T_partials_return x6 =
pow(scaled_diff, 6);
96 const T_partials_return x8 =
pow(scaled_diff, 8);
97 const T_partials_return x10 =
pow(scaled_diff, 10);
98 const T_partials_return temp_p
99 = 0.000658749161529837803157 + 0.0160837851487422766278 / x2
100 + 0.125781726111229246204 / x4 + 0.360344899949804439429 / x6
101 + 0.305326634961232344035 / x8 + 0.0163153871373020978498 / x10;
102 const T_partials_return temp_q
103 = -0.00233520497626869185443 - 0.0605183413124413191178 / x2
104 - 0.527905102951428412248 / x4 - 1.87295284992346047209 / x6
105 - 2.56852019228982242072 / x8 - 1.0 / x10;
107 -
log(-scaled_diff) - x2;
117 T_partials_return dncdf_log = 0.0;
118 T_partials_return t = 0.0;
119 T_partials_return t2 = 0.0;
120 T_partials_return t4 = 0.0;
124 if (scaled_diff > 2.9) {
126 t = 1.0 / (1.0 + 0.3275911 * scaled_diff);
132 * (
exp(x2) - 0.254829592 + 0.284496736 * t - 1.421413741 * t2
133 + 1.453152027 * t2 * t - 1.061405429 * t4));
134 }
else if (scaled_diff > 2.5) {
139 t = scaled_diff - 2.7;
142 dncdf_log = 0.0003849882382 - 0.002079084702 * t + 0.005229340880 * t2
143 - 0.008029540137 * t2 * t + 0.008232190507 * t4
144 - 0.005692364250 * t4 * t + 0.002399496363 *
pow(t, 6);
145 }
else if (scaled_diff > 2.1) {
147 t = scaled_diff - 2.3;
150 dncdf_log = 0.002846135439 - 0.01310032351 * t + 0.02732189391 * t2
151 - 0.03326906904 * t2 * t + 0.02482478940 * t4
152 - 0.009883071924 * t4 * t - 0.0002771362254 *
pow(t, 6);
153 }
else if (scaled_diff > 1.5) {
155 t = scaled_diff - 1.85;
158 dncdf_log = 0.01849212058 - 0.06876280470 * t + 0.1099906382 * t2
159 - 0.09274533184 * t2 * t + 0.03543327418 * t4
160 + 0.005644855518 * t4 * t - 0.01111434424 *
pow(t, 6);
161 }
else if (scaled_diff > 0.8) {
163 t = scaled_diff - 1.15;
166 dncdf_log = 0.1585747034 - 0.3898677543 * t + 0.3515963775 * t2
167 - 0.09748053605 * t2 * t - 0.04347986191 * t4
168 + 0.02182506378 * t4 * t + 0.01074751427 *
pow(t, 6);
169 }
else if (scaled_diff > 0.1) {
171 t = scaled_diff - 0.45;
174 dncdf_log = 0.6245634904 - 0.9521866949 * t + 0.3986215682 * t2
175 + 0.04700850676 * t2 * t - 0.03478651979 * t4
176 - 0.01772675404 * t4 * t + 0.0006577254811 *
pow(t, 6);
177 }
else if (10.0 *
log(
fabs(scaled_diff))
178 <
log(std::numeric_limits<T_partials_return>::max())) {
183 t = 1.0 / (1.0 - 0.3275911 * scaled_diff);
189 * (0.254829592 * t - 0.284496736 * t2 + 1.421413741 * t2 * t
190 - 1.453152027 * t4 + 1.061405429 * t4 * t));
193 if (scaled_diff < -29.0) {
194 dncdf_log += 0.0015065154280332 * x2
195 - 0.3993154819705530 * scaled_diff - 4.2919418242931700;
196 }
else if (scaled_diff < -17.0) {
197 dncdf_log += 0.0001263257217272 * x2 * scaled_diff
198 + 0.0123586859488623 * x2
199 - 0.0860505264736028 * scaled_diff - 1.252783383752970;
200 }
else if (scaled_diff < -7.0) {
201 dncdf_log += 0.000471585349920831 * x2 * scaled_diff
202 + 0.0296839305424034 * x2
203 + 0.207402143352332 * scaled_diff + 0.425316974683324;
204 }
else if (scaled_diff < -3.9) {
205 dncdf_log += -0.0006972280656443 * x2 * scaled_diff
206 + 0.0068218494628567 * x2
207 + 0.0585761964460277 * scaled_diff + 0.1034397670201370;
208 }
else if (scaled_diff < -2.1) {
209 dncdf_log += -0.0018742199480885 * x2 * scaled_diff
210 - 0.0097119598291202 * x2
211 - 0.0170137970924080 * scaled_diff - 0.0100428567412041;
218 partials<0>(ops_partials)[n] += dncdf_log / sigma_sqrt2;
221 partials<1>(ops_partials)[n] -= dncdf_log / sigma_sqrt2;
224 partials<2>(ops_partials)[n] -= dncdf_log * scaled_diff / sigma_dbl;
228 return ops_partials.build(cdf_log);
scalar_seq_view provides a uniform sequence-like wrapper around either a scalar or a sequence of scal...
require_all_not_t< is_nonscalar_prim_or_rev_kernel_expression< std::decay_t< Types > >... > require_all_not_nonscalar_prim_or_rev_kernel_expression_t
Require none of the types satisfy is_nonscalar_prim_or_rev_kernel_expression.
return_type_t< T_y_cl, T_loc_cl, T_scale_cl > normal_lcdf(const T_y_cl &y, const T_loc_cl &mu, const T_scale_cl &sigma)
Returns the normal log complementary cumulative distribution function for the given location,...
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
static constexpr double negative_infinity()
Return negative infinity.
static constexpr double LOG_HALF
The natural logarithm of 0.5, .
static constexpr double positive_infinity()
Return positive infinity.
bool size_zero(const T &x)
Returns 1 if input is of length 0, returns 0 otherwise.
auto pow(const T1 &x1, const T2 &x2)
fvar< T > log(const fvar< T > &x)
bool is_not_nan(const T_y &y)
Return true if y is not NaN.
static constexpr double SQRT_TWO
The value of the square root of 2, .
static constexpr double SQRT_PI
The value of the square root of , .
void check_consistent_sizes(const char *)
Trivial no input case, this function is a no-op.
fvar< T > erfc(const fvar< T > &x)
fvar< T > log1p(const fvar< T > &x)
void check_finite(const char *function, const char *name, const T_y &y)
Return true if all values in y are finite.
void check_not_nan(const char *function, const char *name, const T_y &y)
Check if y is not NaN.
static constexpr double INV_SQRT_PI
The value of 1 over the square root of , .
void check_positive(const char *function, const char *name, const T_y &y)
Check if y is positive.
int64_t max_size(const T1 &x1, const Ts &... xs)
Calculate the size of the largest input.
auto make_partials_propagator(Ops &&... ops)
Construct an partials_propagator.
fvar< T > fabs(const fvar< T > &x)
fvar< T > square(const fvar< T > &x)
fvar< T > exp(const fvar< T > &x)
typename ref_type_if< true, T >::type ref_type_t
typename partials_return_type< Args... >::type partials_return_t
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Extends std::true_type when instantiated with zero or more template parameters, all of which extend t...