|
7 | 7 | #include <stan/math/prim/fun/identity_constrain.hpp> |
8 | 8 | #include <stan/math/prim/fun/multiply_log.hpp> |
9 | 9 | #include <stan/math/prim/fun/size.hpp> |
10 | | -#include <stan/math/prim/fun/sum.hpp> |
11 | | -#include <stan/math/prim/fun/to_ref.hpp> |
12 | | -#include <stan/math/prim/functor/apply.hpp> |
13 | 10 | #include <cmath> |
14 | 11 |
|
15 | 12 | namespace stan { |
@@ -38,27 +35,19 @@ namespace math { |
38 | 35 | * @throw std::domain_error if sigma <= 0 |
39 | 36 | * @throw std::domain_error if mu is not finite |
40 | 37 | */ |
41 | | -template <typename T, typename M, typename S, |
42 | | - require_all_not_nonscalar_prim_or_rev_kernel_expression_t< |
43 | | - T, M, S>* = nullptr> |
44 | | -inline auto offset_multiplier_constrain(const T& x, const M& mu, |
45 | | - const S& sigma) { |
46 | | - const auto& mu_ref = to_ref(mu); |
47 | | - const auto& sigma_ref = to_ref(sigma); |
48 | | - if (is_matrix<T>::value && is_matrix<M>::value) { |
49 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); |
50 | | - } |
51 | | - if (is_matrix<T>::value && is_matrix<S>::value) { |
52 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", sigma); |
53 | | - } else if (is_matrix<M>::value && is_matrix<S>::value) { |
54 | | - check_matching_dims("offset_multiplier_constrain", "mu", mu, "sigma", |
55 | | - sigma); |
| 38 | +template <typename T, typename M, typename S> |
| 39 | +inline return_type_t<T, M, S> offset_multiplier_constrain(const T& x, |
| 40 | + const M& mu, |
| 41 | + const S& sigma) { |
| 42 | + check_finite("offset_multiplier_constrain", "offset", mu); |
| 43 | + if (sigma == 1) { |
| 44 | + if (mu == 0) { |
| 45 | + return identity_constrain(x); |
| 46 | + } |
| 47 | + return mu + x; |
56 | 48 | } |
57 | | - |
58 | | - check_finite("offset_multiplier_constrain", "offset", value_of_rec(mu_ref)); |
59 | | - check_positive_finite("offset_multiplier_constrain", "multiplier", |
60 | | - value_of_rec(sigma_ref)); |
61 | | - return fma(sigma_ref, x, mu_ref); |
| 49 | + check_positive_finite("offset_multiplier_constrain", "multiplier", sigma); |
| 50 | + return fma(sigma, x, mu); |
62 | 51 | } |
63 | 52 |
|
64 | 53 | /** |
@@ -87,223 +76,22 @@ inline auto offset_multiplier_constrain(const T& x, const M& mu, |
87 | 76 | * @throw std::domain_error if sigma <= 0 |
88 | 77 | * @throw std::domain_error if mu is not finite |
89 | 78 | */ |
90 | | -template <typename T, typename M, typename S, |
91 | | - require_all_not_nonscalar_prim_or_rev_kernel_expression_t< |
92 | | - T, M, S>* = nullptr> |
93 | | -inline auto offset_multiplier_constrain(const T& x, const M& mu, const S& sigma, |
94 | | - return_type_t<T, M, S>& lp) { |
95 | | - const auto& mu_ref = to_ref(mu); |
96 | | - const auto& sigma_ref = to_ref(sigma); |
97 | | - if (is_matrix<T>::value && is_matrix<M>::value) { |
98 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); |
99 | | - } |
100 | | - if (is_matrix<T>::value && is_matrix<S>::value) { |
101 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", sigma); |
102 | | - } else if (is_matrix<M>::value && is_matrix<S>::value) { |
103 | | - check_matching_dims("offset_multiplier_constrain", "mu", mu, "sigma", |
104 | | - sigma); |
105 | | - } |
106 | | - |
107 | | - check_finite("offset_multiplier_constrain", "offset", value_of_rec(mu_ref)); |
108 | | - check_positive_finite("offset_multiplier_constrain", "multiplier", |
109 | | - value_of_rec(sigma_ref)); |
110 | | - if (math::size(sigma_ref) == 1) { |
111 | | - lp += sum(multiply_log(math::size(x), sigma_ref)); |
112 | | - } else { |
113 | | - lp += sum(log(sigma_ref)); |
114 | | - } |
115 | | - return fma(sigma_ref, x, mu_ref); |
116 | | -} |
117 | | - |
118 | | -/** |
119 | | - * Overload for array of x and non-array mu and sigma |
120 | | - */ |
121 | | -template <typename T, typename M, typename S, |
122 | | - require_all_not_std_vector_t<M, S>* = nullptr> |
123 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, const M& mu, |
124 | | - const S& sigma) { |
125 | | - std::vector< |
126 | | - plain_type_t<decltype(offset_multiplier_constrain(x[0], mu, sigma))>> |
127 | | - ret; |
128 | | - ret.reserve(x.size()); |
129 | | - const auto& mu_ref = to_ref(mu); |
130 | | - const auto& sigma_ref = to_ref(sigma); |
131 | | - for (size_t i = 0; i < x.size(); ++i) { |
132 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu_ref, sigma_ref)); |
133 | | - } |
134 | | - return ret; |
135 | | -} |
136 | | - |
137 | | -/** |
138 | | - * Overload for array of x and non-array mu and sigma with lp |
139 | | - */ |
140 | | -template <typename T, typename M, typename S, |
141 | | - require_all_not_std_vector_t<M, S>* = nullptr> |
142 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, const M& mu, |
143 | | - const S& sigma, |
144 | | - return_type_t<T, M, S>& lp) { |
145 | | - std::vector< |
146 | | - plain_type_t<decltype(offset_multiplier_constrain(x[0], mu, sigma, lp))>> |
147 | | - ret; |
148 | | - ret.reserve(x.size()); |
149 | | - const auto& mu_ref = to_ref(mu); |
150 | | - const auto& sigma_ref = to_ref(sigma); |
151 | | - for (size_t i = 0; i < x.size(); ++i) { |
152 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu_ref, sigma_ref, lp)); |
153 | | - } |
154 | | - return ret; |
155 | | -} |
156 | | - |
157 | | -/** |
158 | | - * Overload for array of x and sigma and non-array mu |
159 | | - */ |
160 | | -template <typename T, typename M, typename S, |
161 | | - require_not_std_vector_t<M>* = nullptr> |
162 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, const M& mu, |
163 | | - const std::vector<S>& sigma) { |
164 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", sigma); |
165 | | - std::vector< |
166 | | - plain_type_t<decltype(offset_multiplier_constrain(x[0], mu, sigma[0]))>> |
167 | | - ret; |
168 | | - ret.reserve(x.size()); |
169 | | - const auto& mu_ref = to_ref(mu); |
170 | | - for (size_t i = 0; i < x.size(); ++i) { |
171 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu_ref, sigma[i])); |
172 | | - } |
173 | | - return ret; |
174 | | -} |
175 | | - |
176 | | -/** |
177 | | - * Overload for array of x and sigma and non-array mu with lp |
178 | | - */ |
179 | | -template <typename T, typename M, typename S, |
180 | | - require_not_std_vector_t<M>* = nullptr> |
181 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, const M& mu, |
182 | | - const std::vector<S>& sigma, |
183 | | - return_type_t<T, M, S>& lp) { |
184 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", sigma); |
185 | | - std::vector<plain_type_t<decltype( |
186 | | - offset_multiplier_constrain(x[0], mu, sigma[0], lp))>> |
187 | | - ret; |
188 | | - ret.reserve(x.size()); |
189 | | - const auto& mu_ref = to_ref(mu); |
190 | | - for (size_t i = 0; i < x.size(); ++i) { |
191 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu_ref, sigma[i], lp)); |
192 | | - } |
193 | | - return ret; |
194 | | -} |
195 | | - |
196 | | -/** |
197 | | - * Overload for array of x and mu and non-array sigma |
198 | | - */ |
199 | | -template <typename T, typename M, typename S, |
200 | | - require_not_std_vector_t<S>* = nullptr> |
201 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, |
202 | | - const std::vector<M>& mu, |
203 | | - const S& sigma) { |
204 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); |
205 | | - std::vector< |
206 | | - plain_type_t<decltype(offset_multiplier_constrain(x[0], mu[0], sigma))>> |
207 | | - ret; |
208 | | - ret.reserve(x.size()); |
209 | | - const auto& sigma_ref = to_ref(sigma); |
210 | | - for (size_t i = 0; i < x.size(); ++i) { |
211 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu[i], sigma_ref)); |
212 | | - } |
213 | | - return ret; |
214 | | -} |
215 | | - |
216 | | -/** |
217 | | - * Overload for array of x and mu and non-array sigma with lp |
218 | | - */ |
219 | | -template <typename T, typename M, typename S, |
220 | | - require_not_std_vector_t<S>* = nullptr> |
221 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, |
222 | | - const std::vector<M>& mu, |
223 | | - const S& sigma, |
224 | | - return_type_t<T, M, S>& lp) { |
225 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); |
226 | | - std::vector<plain_type_t<decltype( |
227 | | - offset_multiplier_constrain(x[0], mu[0], sigma, lp))>> |
228 | | - ret; |
229 | | - ret.reserve(x.size()); |
230 | | - const auto& sigma_ref = to_ref(sigma); |
231 | | - for (size_t i = 0; i < x.size(); ++i) { |
232 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu[i], sigma_ref, lp)); |
233 | | - } |
234 | | - return ret; |
235 | | -} |
236 | | - |
237 | | -/** |
238 | | - * Overload for array of x, mu, and sigma |
239 | | - */ |
240 | | -template <typename T, typename M, typename S> |
241 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, |
242 | | - const std::vector<M>& mu, |
243 | | - const std::vector<S>& sigma) { |
244 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); |
245 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", sigma); |
246 | | - std::vector<plain_type_t<decltype( |
247 | | - offset_multiplier_constrain(x[0], mu[0], sigma[0]))>> |
248 | | - ret; |
249 | | - ret.reserve(x.size()); |
250 | | - for (size_t i = 0; i < x.size(); ++i) { |
251 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu[i], sigma[i])); |
252 | | - } |
253 | | - return ret; |
254 | | -} |
255 | | - |
256 | | -/** |
257 | | - * Overload for array of x, mu, and sigma with lp |
258 | | - */ |
259 | 79 | template <typename T, typename M, typename S> |
260 | | -inline auto offset_multiplier_constrain(const std::vector<T>& x, |
261 | | - const std::vector<M>& mu, |
262 | | - const std::vector<S>& sigma, |
263 | | - return_type_t<T, M, S>& lp) { |
264 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "mu", mu); |
265 | | - check_matching_dims("offset_multiplier_constrain", "x", x, "sigma", sigma); |
266 | | - std::vector<plain_type_t<decltype( |
267 | | - offset_multiplier_constrain(x[0], mu[0], sigma[0], lp))>> |
268 | | - ret; |
269 | | - ret.reserve(x.size()); |
270 | | - for (size_t i = 0; i < x.size(); ++i) { |
271 | | - ret.emplace_back(offset_multiplier_constrain(x[i], mu[i], sigma[i], lp)); |
272 | | - } |
273 | | - return ret; |
274 | | -} |
275 | | - |
276 | | -/** |
277 | | - * Return the linearly transformed value for the specified unconstrained input |
278 | | - * and specified offset and multiplier. If the `Jacobian` parameter is `true`, |
279 | | - * the log density accumulator is incremented with the log absolute Jacobian |
280 | | - * determinant of the transform. All of the transforms are specified with their |
281 | | - * Jacobians in the *Stan Reference Manual* chapter Constraint Transforms. |
282 | | - * |
283 | | - * @tparam Jacobian if `true`, increment log density accumulator with log |
284 | | - * absolute Jacobian determinant of constraining transform |
285 | | - * @tparam T A type inheriting from `Eigen::EigenBase`, a `var_value` with inner |
286 | | - * type inheriting from `Eigen::EigenBase`, a standard vector, or a scalar |
287 | | - * @tparam M A type inheriting from `Eigen::EigenBase`, a `var_value` with inner |
288 | | - * type inheriting from `Eigen::EigenBase`, a standard vector, or a scalar |
289 | | - * @tparam S A type inheriting from `Eigen::EigenBase`, a `var_value` with inner |
290 | | - * type inheriting from `Eigen::EigenBase`, a standard vector, or a scalar |
291 | | - * @param[in] x Unconstrained scalar input |
292 | | - * @param[in] mu offset of constrained output |
293 | | - * @param[in] sigma multiplier of constrained output |
294 | | - * @param[in, out] lp log density accumulator |
295 | | - * @return linear transformed value corresponding to inputs |
296 | | - * @throw std::domain_error if sigma <= 0 |
297 | | - * @throw std::domain_error if mu is not finite |
298 | | - */ |
299 | | -template <bool Jacobian, typename T, typename M, typename S> |
300 | | -inline auto offset_multiplier_constrain(const T& x, const M& mu, const S& sigma, |
301 | | - return_type_t<T, M, S>& lp) { |
302 | | - if (Jacobian) { |
303 | | - return offset_multiplier_constrain(x, mu, sigma, lp); |
304 | | - } else { |
305 | | - return offset_multiplier_constrain(x, mu, sigma); |
| 80 | +inline return_type_t<T, M, S> offset_multiplier_constrain(const T& x, |
| 81 | + const M& mu, |
| 82 | + const S& sigma, |
| 83 | + T& lp) { |
| 84 | + using std::log; |
| 85 | + check_finite("offset_multiplier_constrain", "offset", mu); |
| 86 | + if (sigma == 1) { |
| 87 | + if (mu == 0) { |
| 88 | + return identity_constrain(x); |
| 89 | + } |
| 90 | + return mu + x; |
306 | 91 | } |
| 92 | + check_positive_finite("offset_multiplier_constrain", "multiplier", sigma); |
| 93 | + lp += multiply_log(math::size(x), sigma); |
| 94 | + return fma(sigma, x, mu); |
307 | 95 | } |
308 | 96 |
|
309 | 97 | } // namespace math |
|
0 commit comments