Skip to content

Commit 09d6e97

Browse files
committed
Merge commit '22b06402baa7aadf8ed6b32a3dfce222493cff47' into HEAD
2 parents d24fe7e + 22b0640 commit 09d6e97

File tree

6 files changed

+120
-488
lines changed

6 files changed

+120
-488
lines changed

stan/math/prim/prob/cauchy_cdf.hpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,30 @@ return_type_t<T_y, T_loc, T_scale> cauchy_cdf(const T_y& y, const T_loc& mu,
3333
const T_scale& sigma) {
3434
using T_partials_return = partials_return_t<T_y, T_loc, T_scale>;
3535
using std::atan;
36+
using T_y_ref = ref_type_t<T_y>;
37+
using T_mu_ref = ref_type_t<T_loc>;
38+
using T_sigma_ref = ref_type_t<T_scale>;
3639
static const char* function = "cauchy_cdf";
37-
check_not_nan(function, "Random variable", y);
38-
check_finite(function, "Location parameter", mu);
39-
check_positive_finite(function, "Scale parameter", sigma);
4040
check_consistent_sizes(function, "Random variable", y, "Location parameter",
4141
mu, "Scale Parameter", sigma);
42+
T_y_ref y_ref = y;
43+
T_mu_ref mu_ref = mu;
44+
T_sigma_ref sigma_ref = sigma;
45+
check_not_nan(function, "Random variable", y_ref);
46+
check_finite(function, "Location parameter", mu_ref);
47+
check_positive_finite(function, "Scale parameter", sigma_ref);
4248

4349
if (size_zero(y, mu, sigma)) {
4450
return 1.0;
4551
}
4652

4753
T_partials_return P(1.0);
48-
operands_and_partials<T_y, T_loc, T_scale> ops_partials(y, mu, sigma);
54+
operands_and_partials<T_y_ref, T_mu_ref, T_sigma_ref> ops_partials(
55+
y_ref, mu_ref, sigma_ref);
4956

50-
scalar_seq_view<T_y> y_vec(y);
51-
scalar_seq_view<T_loc> mu_vec(mu);
52-
scalar_seq_view<T_scale> sigma_vec(sigma);
57+
scalar_seq_view<T_y_ref> y_vec(y_ref);
58+
scalar_seq_view<T_mu_ref> mu_vec(mu_ref);
59+
scalar_seq_view<T_sigma_ref> sigma_vec(sigma_ref);
5360
size_t N = max_size(y, mu, sigma);
5461

5562
// Explicit return for extreme values

stan/math/prim/prob/cauchy_lccdf.hpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,30 @@ return_type_t<T_y, T_loc, T_scale> cauchy_lccdf(const T_y& y, const T_loc& mu,
3535
using T_partials_return = partials_return_t<T_y, T_loc, T_scale>;
3636
using std::atan;
3737
using std::log;
38+
using T_y_ref = ref_type_t<T_y>;
39+
using T_mu_ref = ref_type_t<T_loc>;
40+
using T_sigma_ref = ref_type_t<T_scale>;
3841
static const char* function = "cauchy_lccdf";
39-
check_not_nan(function, "Random variable", y);
40-
check_finite(function, "Location parameter", mu);
41-
check_positive_finite(function, "Scale parameter", sigma);
4242
check_consistent_sizes(function, "Random variable", y, "Location parameter",
4343
mu, "Scale Parameter", sigma);
44+
T_y_ref y_ref = y;
45+
T_mu_ref mu_ref = mu;
46+
T_sigma_ref sigma_ref = sigma;
47+
check_not_nan(function, "Random variable", y_ref);
48+
check_finite(function, "Location parameter", mu_ref);
49+
check_positive_finite(function, "Scale parameter", sigma_ref);
4450

4551
if (size_zero(y, mu, sigma)) {
4652
return 0;
4753
}
4854

4955
T_partials_return ccdf_log(0.0);
50-
operands_and_partials<T_y, T_loc, T_scale> ops_partials(y, mu, sigma);
56+
operands_and_partials<T_y_ref, T_mu_ref, T_sigma_ref> ops_partials(
57+
y_ref, mu_ref, sigma_ref);
5158

52-
scalar_seq_view<T_y> y_vec(y);
53-
scalar_seq_view<T_loc> mu_vec(mu);
54-
scalar_seq_view<T_scale> sigma_vec(sigma);
59+
scalar_seq_view<T_y_ref> y_vec(y_ref);
60+
scalar_seq_view<T_mu_ref> mu_vec(mu_ref);
61+
scalar_seq_view<T_sigma_ref> sigma_vec(sigma_ref);
5562
size_t N = max_size(y, mu, sigma);
5663

5764
for (size_t n = 0; n < N; n++) {

stan/math/prim/prob/cauchy_lcdf.hpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,30 @@ return_type_t<T_y, T_loc, T_scale> cauchy_lcdf(const T_y& y, const T_loc& mu,
3535
using T_partials_return = partials_return_t<T_y, T_loc, T_scale>;
3636
using std::atan;
3737
using std::log;
38+
using T_y_ref = ref_type_t<T_y>;
39+
using T_mu_ref = ref_type_t<T_loc>;
40+
using T_sigma_ref = ref_type_t<T_scale>;
3841
static const char* function = "cauchy_lcdf";
39-
check_not_nan(function, "Random variable", y);
40-
check_finite(function, "Location parameter", mu);
41-
check_positive_finite(function, "Scale parameter", sigma);
4242
check_consistent_sizes(function, "Random variable", y, "Location parameter",
4343
mu, "Scale Parameter", sigma);
44+
T_y_ref y_ref = y;
45+
T_mu_ref mu_ref = mu;
46+
T_sigma_ref sigma_ref = sigma;
47+
check_not_nan(function, "Random variable", y_ref);
48+
check_finite(function, "Location parameter", mu_ref);
49+
check_positive_finite(function, "Scale parameter", sigma_ref);
4450

4551
if (size_zero(y, mu, sigma)) {
4652
return 0;
4753
}
4854

4955
T_partials_return cdf_log(0.0);
50-
operands_and_partials<T_y, T_loc, T_scale> ops_partials(y, mu, sigma);
56+
operands_and_partials<T_y_ref, T_mu_ref, T_sigma_ref> ops_partials(
57+
y_ref, mu_ref, sigma_ref);
5158

52-
scalar_seq_view<T_y> y_vec(y);
53-
scalar_seq_view<T_loc> mu_vec(mu);
54-
scalar_seq_view<T_scale> sigma_vec(sigma);
59+
scalar_seq_view<T_y_ref> y_vec(y_ref);
60+
scalar_seq_view<T_mu_ref> mu_vec(mu_ref);
61+
scalar_seq_view<T_sigma_ref> sigma_vec(sigma_ref);
5562
size_t N = max_size(y, mu, sigma);
5663

5764
for (size_t n = 0; n < N; n++) {

stan/math/prim/prob/cauchy_lpdf.hpp

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <stan/math/prim/fun/max_size.hpp>
1010
#include <stan/math/prim/fun/size.hpp>
1111
#include <stan/math/prim/fun/size_zero.hpp>
12+
#include <stan/math/prim/fun/to_ref.hpp>
1213
#include <stan/math/prim/fun/value_of.hpp>
1314
#include <stan/math/prim/functor/operands_and_partials.hpp>
1415
#include <cmath>
@@ -37,13 +38,17 @@ template <bool propto, typename T_y, typename T_loc, typename T_scale>
3738
return_type_t<T_y, T_loc, T_scale> cauchy_lpdf(const T_y& y, const T_loc& mu,
3839
const T_scale& sigma) {
3940
using T_partials_return = partials_return_t<T_y, T_loc, T_scale>;
41+
using T_partials_array = Eigen::Array<T_partials_return, Eigen::Dynamic, 1>;
4042
using std::log;
43+
using T_y_ref = ref_type_if_t<!is_constant<T_y>::value, T_y>;
44+
using T_mu_ref = ref_type_if_t<!is_constant<T_loc>::value, T_loc>;
45+
using T_sigma_ref = ref_type_if_t<!is_constant<T_scale>::value, T_scale>;
4146
static const char* function = "cauchy_lpdf";
42-
check_not_nan(function, "Random variable", y);
43-
check_finite(function, "Location parameter", mu);
44-
check_positive_finite(function, "Scale parameter", sigma);
4547
check_consistent_sizes(function, "Random variable", y, "Location parameter",
4648
mu, "Scale parameter", sigma);
49+
T_y_ref y_ref = y;
50+
T_mu_ref mu_ref = mu;
51+
T_sigma_ref sigma_ref = sigma;
4752

4853
if (size_zero(y, mu, sigma)) {
4954
return 0.0;
@@ -53,57 +58,76 @@ return_type_t<T_y, T_loc, T_scale> cauchy_lpdf(const T_y& y, const T_loc& mu,
5358
}
5459

5560
T_partials_return logp(0.0);
56-
operands_and_partials<T_y, T_loc, T_scale> ops_partials(y, mu, sigma);
61+
operands_and_partials<T_y_ref, T_mu_ref, T_sigma_ref> ops_partials(
62+
y_ref, mu_ref, sigma_ref);
5763

58-
scalar_seq_view<T_y> y_vec(y);
59-
scalar_seq_view<T_loc> mu_vec(mu);
60-
scalar_seq_view<T_scale> sigma_vec(sigma);
61-
size_t N = max_size(y, mu, sigma);
64+
const auto& y_col = as_column_vector_or_scalar(y_ref);
65+
const auto& mu_col = as_column_vector_or_scalar(mu_ref);
66+
const auto& sigma_col = as_column_vector_or_scalar(sigma_ref);
6267

63-
VectorBuilder<true, T_partials_return, T_scale> inv_sigma(size(sigma));
64-
VectorBuilder<true, T_partials_return, T_scale> sigma_squared(size(sigma));
65-
VectorBuilder<include_summand<propto, T_scale>::value, T_partials_return,
66-
T_scale>
67-
log_sigma(size(sigma));
68-
for (size_t i = 0; i < stan::math::size(sigma); i++) {
69-
const T_partials_return sigma_dbl = value_of(sigma_vec[i]);
70-
inv_sigma[i] = 1.0 / sigma_dbl;
71-
sigma_squared[i] = sigma_dbl * sigma_dbl;
72-
if (include_summand<propto, T_scale>::value) {
73-
log_sigma[i] = log(sigma_dbl);
74-
}
75-
}
68+
const auto& y_arr = as_array_or_scalar(y_col);
69+
const auto& mu_arr = as_array_or_scalar(mu_col);
70+
const auto& sigma_arr = as_array_or_scalar(sigma_col);
7671

77-
for (size_t n = 0; n < N; n++) {
78-
const T_partials_return y_dbl = value_of(y_vec[n]);
79-
const T_partials_return mu_dbl = value_of(mu_vec[n]);
72+
ref_type_t<decltype(value_of(y_arr))> y_val = value_of(y_arr);
73+
ref_type_t<decltype(value_of(mu_arr))> mu_val = value_of(mu_arr);
74+
ref_type_t<decltype(value_of(sigma_arr))> sigma_val = value_of(sigma_arr);
75+
check_not_nan(function, "Random variable", y_val);
76+
check_finite(function, "Location parameter", mu_val);
77+
check_positive_finite(function, "Scale parameter", sigma_val);
8078

81-
const T_partials_return y_minus_mu = y_dbl - mu_dbl;
82-
const T_partials_return y_minus_mu_squared = y_minus_mu * y_minus_mu;
83-
const T_partials_return y_minus_mu_over_sigma = y_minus_mu * inv_sigma[n];
84-
const T_partials_return y_minus_mu_over_sigma_squared
85-
= y_minus_mu_over_sigma * y_minus_mu_over_sigma;
79+
size_t N = max_size(y, mu, sigma);
8680

87-
if (include_summand<propto>::value) {
88-
logp -= LOG_PI;
89-
}
90-
if (include_summand<propto, T_scale>::value) {
91-
logp -= log_sigma[n];
92-
}
93-
logp -= log1p(y_minus_mu_over_sigma_squared);
81+
const auto& inv_sigma
82+
= to_ref_if<!is_constant_all<T_scale>::value>(inv(sigma_val));
83+
const auto& y_minus_mu
84+
= to_ref_if<!is_constant_all<T_y, T_loc, T_scale>::value>(y_val - mu_val);
9485

95-
if (!is_constant_all<T_y>::value) {
96-
ops_partials.edge1_.partials_[n]
97-
-= 2 * y_minus_mu / (sigma_squared[n] + y_minus_mu_squared);
98-
}
99-
if (!is_constant_all<T_loc>::value) {
100-
ops_partials.edge2_.partials_[n]
101-
+= 2 * y_minus_mu / (sigma_squared[n] + y_minus_mu_squared);
86+
logp -= sum(log1p(square(y_minus_mu * inv_sigma)));
87+
if (include_summand<propto>::value) {
88+
logp -= N * LOG_PI;
89+
}
90+
if (include_summand<propto, T_scale>::value) {
91+
logp -= sum(log(sigma_val)) * N / size(sigma);
92+
}
93+
94+
if (!is_constant_all<T_y, T_loc, T_scale>::value) {
95+
const auto& sigma_squared
96+
= to_ref_if<!is_constant_all<T_scale>::value>(square(sigma_val));
97+
const auto& y_minus_mu_squared
98+
= to_ref_if<!is_constant_all<T_scale>::value>(square(y_minus_mu));
99+
if (!is_constant_all<T_y, T_loc>::value) {
100+
const auto& mu_deriv
101+
= to_ref_if < !is_constant_all<T_y>::value
102+
&& !is_constant_all<T_loc>::value
103+
> (2 * y_minus_mu / (sigma_squared + y_minus_mu_squared));
104+
if (!is_constant_all<T_y>::value) {
105+
if (is_vector<T_y>::value) {
106+
ops_partials.edge1_.partials_
107+
= forward_as<T_partials_array>(-mu_deriv);
108+
} else {
109+
ops_partials.edge1_.partials_[0] = -sum(mu_deriv);
110+
}
111+
}
112+
if (!is_constant_all<T_loc>::value) {
113+
if (is_vector<T_loc>::value) {
114+
ops_partials.edge2_.partials_
115+
= std::move(forward_as<T_partials_array>(mu_deriv));
116+
} else {
117+
ops_partials.edge2_.partials_[0] = sum(mu_deriv);
118+
}
119+
}
102120
}
103121
if (!is_constant_all<T_scale>::value) {
104-
ops_partials.edge3_.partials_[n]
105-
+= (y_minus_mu_squared - sigma_squared[n]) * inv_sigma[n]
106-
/ (sigma_squared[n] + y_minus_mu_squared);
122+
if (is_vector<T_scale>::value) {
123+
ops_partials.edge3_.partials_ = forward_as<T_partials_array>(
124+
(y_minus_mu_squared - sigma_squared) * inv_sigma
125+
/ (sigma_squared + y_minus_mu_squared));
126+
} else {
127+
ops_partials.edge3_.partials_[0]
128+
= sum((y_minus_mu_squared - sigma_squared) * inv_sigma
129+
/ (sigma_squared + y_minus_mu_squared));
130+
}
107131
}
108132
}
109133
return ops_partials.build(logp);

stan/math/prim/prob/cauchy_rng.hpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,17 @@ inline typename VectorBuilder<true, double, T_loc, T_scale>::type cauchy_rng(
3434
using boost::variate_generator;
3535
using boost::random::cauchy_distribution;
3636
static const char* function = "cauchy_rng";
37-
check_finite(function, "Location parameter", mu);
38-
check_positive_finite(function, "Scale parameter", sigma);
37+
using T_mu_ref = ref_type_t<T_loc>;
38+
using T_sigma_ref = ref_type_t<T_scale>;
3939
check_consistent_sizes(function, "Location parameter", mu, "Scale Parameter",
4040
sigma);
41+
T_mu_ref mu_ref = mu;
42+
T_sigma_ref sigma_ref = sigma;
43+
check_finite(function, "Location parameter", mu_ref);
44+
check_positive_finite(function, "Scale parameter", sigma_ref);
4145

42-
scalar_seq_view<T_loc> mu_vec(mu);
43-
scalar_seq_view<T_scale> sigma_vec(sigma);
46+
scalar_seq_view<T_mu_ref> mu_vec(mu_ref);
47+
scalar_seq_view<T_sigma_ref> sigma_vec(sigma_ref);
4448
size_t N = max_size(mu, sigma);
4549
VectorBuilder<true, double, T_loc, T_scale> output(N);
4650

0 commit comments

Comments
 (0)