8
8
#include < stan/math/prim/fun/max_size.hpp>
9
9
#include < stan/math/prim/fun/size.hpp>
10
10
#include < stan/math/prim/fun/size_zero.hpp>
11
+ #include < stan/math/prim/fun/to_ref.hpp>
11
12
#include < stan/math/prim/fun/value_of.hpp>
12
13
#include < stan/math/prim/functor/operands_and_partials.hpp>
13
14
#include < cmath>
@@ -34,60 +35,63 @@ return_type_t<T_y, T_shape, T_scale> weibull_cdf(const T_y& y,
34
35
const T_shape& alpha,
35
36
const T_scale& sigma) {
36
37
using T_partials_return = partials_return_t <T_y, T_shape, T_scale>;
37
- using std::exp ;
38
- using std::log ;
38
+ using T_y_ref = ref_type_if_t <!is_constant<T_y>::value, T_y>;
39
+ using T_alpha_ref = ref_type_if_t <!is_constant<T_shape>::value, T_shape>;
40
+ using T_sigma_ref = ref_type_if_t <!is_constant<T_scale>::value, T_scale>;
39
41
using std::pow ;
40
42
static const char * function = " weibull_cdf" ;
41
- check_nonnegative (function, " Random variable" , y);
42
- check_positive_finite (function, " Shape parameter" , alpha);
43
- check_positive_finite (function, " Scale parameter" , sigma);
43
+
44
+ T_y_ref y_ref = y;
45
+ T_alpha_ref alpha_ref = alpha;
46
+ T_sigma_ref sigma_ref = sigma;
47
+
48
+ const auto & y_col = as_column_vector_or_scalar (y_ref);
49
+ const auto & alpha_col = as_column_vector_or_scalar (alpha_ref);
50
+ const auto & sigma_col = as_column_vector_or_scalar (sigma_ref);
51
+
52
+ const auto & y_arr = as_array_or_scalar (y_col);
53
+ const auto & alpha_arr = as_array_or_scalar (alpha_col);
54
+ const auto & sigma_arr = as_array_or_scalar (sigma_col);
55
+
56
+ ref_type_t <decltype (value_of (y_arr))> y_val = value_of (y_arr);
57
+ ref_type_t <decltype (value_of (alpha_arr))> alpha_val = value_of (alpha_arr);
58
+ ref_type_t <decltype (value_of (sigma_arr))> sigma_val = value_of (sigma_arr);
59
+
60
+ check_nonnegative (function, " Random variable" , y_val);
61
+ check_positive_finite (function, " Shape parameter" , alpha_val);
62
+ check_positive_finite (function, " Scale parameter" , sigma_val);
44
63
45
64
if (size_zero (y, alpha, sigma)) {
46
65
return 1.0 ;
47
66
}
48
67
49
- T_partials_return cdf ( 1.0 );
50
- operands_and_partials<T_y, T_shape, T_scale> ops_partials (y, alpha, sigma );
68
+ operands_and_partials<T_y_ref, T_alpha_ref, T_sigma_ref> ops_partials (
69
+ y_ref, alpha_ref, sigma_ref );
51
70
52
- scalar_seq_view<T_y> y_vec (y);
53
- scalar_seq_view<T_scale> sigma_vec (sigma);
54
- scalar_seq_view<T_shape> alpha_vec (alpha);
55
- size_t N = max_size (y, sigma, alpha);
56
- for (size_t n = 0 ; n < N; n++) {
57
- const T_partials_return y_dbl = value_of (y_vec[n]);
58
- const T_partials_return sigma_dbl = value_of (sigma_vec[n]);
59
- const T_partials_return alpha_dbl = value_of (alpha_vec[n]);
60
- const T_partials_return pow_n = pow (y_dbl / sigma_dbl, alpha_dbl);
61
- const T_partials_return exp_n = exp (-pow_n);
62
- const T_partials_return cdf_n = 1.0 - exp_n;
71
+ constexpr bool any_derivs = !is_constant_all<T_y, T_shape, T_scale>::value;
72
+ const auto & pow_n = to_ref_if<any_derivs>(pow (y_val / sigma_val, alpha_val));
73
+ const auto & exp_n = to_ref_if<any_derivs>(exp (-pow_n));
74
+ const auto & cdf_n = to_ref_if<any_derivs>(1 - exp_n);
63
75
64
- cdf *= cdf_n;
76
+ T_partials_return cdf = prod ( cdf_n) ;
65
77
66
- const T_partials_return rep_deriv = exp_n * pow_n / cdf_n;
67
- if (!is_constant_all<T_y>::value) {
68
- ops_partials.edge1_ .partials_ [n] += rep_deriv * alpha_dbl / y_dbl;
78
+ if (any_derivs) {
79
+ const auto & rep_deriv = to_ref_if<(!is_constant_all<T_y, T_scale>::value
80
+ && !is_constant_all<T_shape>::value)>(
81
+ exp_n * pow_n * cdf / cdf_n);
82
+ if (!is_constant_all<T_y, T_scale>::value) {
83
+ const auto & deriv_y_sigma = to_ref_if<(
84
+ !is_constant_all<T_y>::value && !is_constant_all<T_scale>::value)>(
85
+ rep_deriv * alpha_val);
86
+ if (!is_constant_all<T_y>::value) {
87
+ ops_partials.edge1_ .partials_ = deriv_y_sigma / y_val;
88
+ }
89
+ if (!is_constant_all<T_scale>::value) {
90
+ ops_partials.edge3_ .partials_ = -deriv_y_sigma / sigma_val;
91
+ }
69
92
}
70
93
if (!is_constant_all<T_shape>::value) {
71
- ops_partials.edge2_ .partials_ [n] += rep_deriv * log (y_dbl / sigma_dbl);
72
- }
73
- if (!is_constant_all<T_scale>::value) {
74
- ops_partials.edge3_ .partials_ [n] -= rep_deriv * alpha_dbl / sigma_dbl;
75
- }
76
- }
77
-
78
- if (!is_constant_all<T_y>::value) {
79
- for (size_t n = 0 ; n < stan::math::size (y); ++n) {
80
- ops_partials.edge1_ .partials_ [n] *= cdf;
81
- }
82
- }
83
- if (!is_constant_all<T_shape>::value) {
84
- for (size_t n = 0 ; n < stan::math::size (alpha); ++n) {
85
- ops_partials.edge2_ .partials_ [n] *= cdf;
86
- }
87
- }
88
- if (!is_constant_all<T_scale>::value) {
89
- for (size_t n = 0 ; n < stan::math::size (sigma); ++n) {
90
- ops_partials.edge3_ .partials_ [n] *= cdf;
94
+ ops_partials.edge2_ .partials_ = rep_deriv * log (y_val / sigma_val);
91
95
}
92
96
}
93
97
return ops_partials.build (cdf);
0 commit comments