Automatic Differentiation
 
Loading...
Searching...
No Matches
lub_constrain.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_FUN_LUB_CONSTRAIN_HPP
2#define STAN_MATH_PRIM_FUN_LUB_CONSTRAIN_HPP
3
19#include <cmath>
20
21namespace stan {
22namespace math {
23
43template <typename T, typename L, typename U,
44 require_all_stan_scalar_t<T, L, U>* = nullptr,
45 require_not_var_t<return_type_t<T, L, U>>* = nullptr>
46inline auto lub_constrain(T&& x, L&& lb, U&& ub) {
47 const bool is_lb_inf = value_of(lb) == NEGATIVE_INFTY;
48 const bool is_ub_inf = value_of(ub) == INFTY;
49 if (unlikely(is_ub_inf && is_lb_inf)) {
50 return identity_constrain(x, lb, ub);
51 } else if (unlikely(is_ub_inf)) {
52 return lb_constrain(identity_constrain(x, ub), lb);
53 } else if (unlikely(is_lb_inf)) {
54 return ub_constrain(identity_constrain(x, lb), ub);
55 } else {
56 check_less("lub_constrain", "lb", value_of(lb), value_of(ub));
57 return (ub - lb) * inv_logit(x) + lb;
58 }
59}
60
94template <typename T, typename L, typename U,
97inline auto lub_constrain(T&& x, L&& lb, U&& ub, return_type_t<T, L, U>& lp) {
98 const bool is_lb_inf = value_of(lb) == NEGATIVE_INFTY;
99 const bool is_ub_inf = value_of(ub) == INFTY;
100 if (unlikely(is_ub_inf && is_lb_inf)) {
101 return identity_constrain(x, ub, lb);
102 } else if (unlikely(is_ub_inf)) {
103 return lb_constrain(identity_constrain(x, ub), lb, lp);
104 } else if (unlikely(is_lb_inf)) {
105 return ub_constrain(identity_constrain(x, lb), ub, lp);
106 } else {
107 check_less("lub_constrain", "lb", value_of(lb), value_of(ub));
108 const auto diff = ub - lb;
109 lp += add(log(diff), subtract(-abs(x), multiply(2.0, log1p_exp(-abs(x)))));
110 return diff * inv_logit(x) + lb;
111 }
112}
113
117template <typename T, typename L, typename U, require_eigen_t<T>* = nullptr,
118 require_all_stan_scalar_t<L, U>* = nullptr,
119 require_not_var_t<return_type_t<T, L, U>>* = nullptr>
120inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
121 return eval(
122 x.unaryExpr([ub, lb](auto&& xx) { return lub_constrain(xx, lb, ub); }));
123}
124
128template <typename T, typename L, typename U, require_eigen_t<T>* = nullptr,
129 require_all_stan_scalar_t<L, U>* = nullptr,
130 require_not_var_t<return_type_t<T, L, U>>* = nullptr>
131inline auto lub_constrain(const T& x, const L& lb, const U& ub,
133 return eval(x.unaryExpr(
134 [lb, ub, &lp](auto&& xx) { return lub_constrain(xx, lb, ub, lp); }));
135}
136
141template <typename T, typename L, typename U,
142 require_all_eigen_t<T, L>* = nullptr,
143 require_stan_scalar_t<U>* = nullptr,
145inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
146 check_matching_dims("lub_constrain", "x", x, "lb", lb);
147 return eval(x.binaryExpr(
148 lb, [ub](auto&& x, auto&& lb) { return lub_constrain(x, lb, ub); }));
149}
150
155template <typename T, typename L, typename U,
156 require_all_eigen_t<T, L>* = nullptr,
157 require_stan_scalar_t<U>* = nullptr,
158 require_not_var_t<return_type_t<T, L, U>>* = nullptr>
159inline auto lub_constrain(const T& x, const L& lb, const U& ub,
160 return_type_t<T, L, U>& lp) {
161 check_matching_dims("lub_constrain", "x", x, "lb", lb);
162 return eval(x.binaryExpr(lb, [ub, &lp](auto&& x, auto&& lb) {
163 return lub_constrain(x, lb, ub, lp);
164 }));
165}
166
171template <typename T, typename L, typename U,
172 require_all_eigen_t<T, U>* = nullptr,
173 require_stan_scalar_t<L>* = nullptr,
174 require_not_var_t<return_type_t<T, L, U>>* = nullptr>
175inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
176 check_matching_dims("lub_constrain", "x", x, "ub", ub);
177 return eval(x.binaryExpr(
178 ub, [lb](auto&& x, auto&& ub) { return lub_constrain(x, lb, ub); }));
179}
180
185template <typename T, typename L, typename U,
186 require_all_eigen_t<T, U>* = nullptr,
187 require_stan_scalar_t<L>* = nullptr,
188 require_not_var_t<return_type_t<T, L, U>>* = nullptr>
189inline auto lub_constrain(const T& x, const L& lb, const U& ub,
190 return_type_t<T, L, U>& lp) {
191 check_matching_dims("lub_constrain", "x", x, "ub", ub);
192 return eval(x.binaryExpr(ub, [lb, &lp](auto&& x, auto&& ub) {
193 return lub_constrain(x, lb, ub, lp);
194 }));
195}
196
200template <typename T, typename L, typename U,
201 require_all_eigen_t<T, L, U>* = nullptr,
202 require_not_var_t<return_type_t<T, L, U>>* = nullptr>
203inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
204 check_matching_dims("lub_constrain", "x", x, "lb", lb);
205 check_matching_dims("lub_constrain", "x", x, "ub", ub);
206 auto x_ref = to_ref(x);
207 auto lb_ref = to_ref(lb);
208 auto ub_ref = to_ref(ub);
209 promote_scalar_t<return_type_t<T, L, U>, T> x_ret(x.rows(), x.cols());
210 for (Eigen::Index j = 0; j < x_ref.cols(); ++j) {
211 for (Eigen::Index i = 0; i < x_ref.rows(); ++i) {
212 x_ret.coeffRef(i, j) = lub_constrain(
213 x_ref.coeff(i, j), lb_ref.coeff(i, j), ub_ref.coeff(i, j));
214 }
215 }
216 return x_ret;
217}
218
222template <typename T, typename L, typename U,
225inline auto lub_constrain(const T& x, const L& lb, const U& ub,
227 check_matching_dims("lub_constrain", "x", x, "lb", lb);
228 check_matching_dims("lub_constrain", "x", x, "ub", ub);
229 auto x_ref = to_ref(x);
230 auto lb_ref = to_ref(lb);
231 auto ub_ref = to_ref(ub);
232 promote_scalar_t<return_type_t<T, L, U>, T> x_ret(x.rows(), x.cols());
233 for (Eigen::Index j = 0; j < x_ref.cols(); ++j) {
234 for (Eigen::Index i = 0; i < x_ref.rows(); ++i) {
235 x_ret.coeffRef(i, j) = lub_constrain(
236 x_ref.coeff(i, j), lb_ref.coeff(i, j), ub_ref.coeff(i, j), lp);
237 }
238 }
239 return x_ret;
240}
241
245template <typename T, typename L, typename U,
246 require_all_not_std_vector_t<L, U>* = nullptr>
247inline auto lub_constrain(const std::vector<T>& x, const L& lb, const U& ub) {
248 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb, ub))>> ret(
249 x.size());
250 for (size_t i = 0; i < x.size(); ++i) {
251 ret[i] = lub_constrain(x[i], lb, ub);
252 }
253 return ret;
254}
255
259template <typename T, typename L, typename U,
261inline auto lub_constrain(const std::vector<T>& x, const L& lb, const U& ub,
263 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb, ub))>> ret(
264 x.size());
265 for (size_t i = 0; i < x.size(); ++i) {
266 ret[i] = lub_constrain(x[i], lb, ub, lp);
267 }
268 return ret;
269}
270
274template <typename T, typename L, typename U,
276inline auto lub_constrain(const std::vector<T>& x, const L& lb,
277 const std::vector<U>& ub) {
278 check_matching_dims("lub_constrain", "x", x, "ub", ub);
279 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb, ub[0]))>> ret(
280 x.size());
281 for (size_t i = 0; i < x.size(); ++i) {
282 ret[i] = lub_constrain(x[i], lb, ub[i]);
283 }
284 return ret;
285}
286
290template <typename T, typename L, typename U,
292inline auto lub_constrain(const std::vector<T>& x, const L& lb,
293 const std::vector<U>& ub,
295 check_matching_dims("lub_constrain", "x", x, "ub", ub);
296 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb, ub[0]))>> ret(
297 x.size());
298 for (size_t i = 0; i < x.size(); ++i) {
299 ret[i] = lub_constrain(x[i], lb, ub[i], lp);
300 }
301 return ret;
302}
303
307template <typename T, typename L, typename U,
309inline auto lub_constrain(const std::vector<T>& x, const std::vector<L>& lb,
310 const U& ub) {
311 check_matching_dims("lub_constrain", "x", x, "lb", lb);
312 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb[0], ub))>> ret(
313 x.size());
314 for (size_t i = 0; i < x.size(); ++i) {
315 ret[i] = lub_constrain(x[i], lb[i], ub);
316 }
317 return ret;
318}
319
323template <typename T, typename L, typename U,
325inline auto lub_constrain(const std::vector<T>& x, const std::vector<L>& lb,
326 const U& ub, return_type_t<T, L, U>& lp) {
327 check_matching_dims("lub_constrain", "x", x, "lb", lb);
328 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb[0], ub))>> ret(
329 x.size());
330 for (size_t i = 0; i < x.size(); ++i) {
331 ret[i] = lub_constrain(x[i], lb[i], ub, lp);
332 }
333 return ret;
334}
335
339template <typename T, typename L, typename U>
340inline auto lub_constrain(const std::vector<T>& x, const std::vector<L>& lb,
341 const std::vector<U>& ub) {
342 check_matching_dims("lub_constrain", "x", x, "lb", lb);
343 check_matching_dims("lub_constrain", "x", x, "ub", ub);
344 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb[0], ub[0]))>> ret(
345 x.size());
346 for (size_t i = 0; i < x.size(); ++i) {
347 ret[i] = lub_constrain(x[i], lb[i], ub[i]);
348 }
349 return ret;
350}
351
355template <typename T, typename L, typename U>
356inline auto lub_constrain(const std::vector<T>& x, const std::vector<L>& lb,
357 const std::vector<U>& ub,
359 check_matching_dims("lub_constrain", "x", x, "lb", lb);
360 check_matching_dims("lub_constrain", "x", x, "ub", ub);
361 std::vector<plain_type_t<decltype(lub_constrain(x[0], lb[0], ub[0]))>> ret(
362 x.size());
363 for (size_t i = 0; i < x.size(); ++i) {
364 ret[i] = lub_constrain(x[i], lb[i], ub[i], lp);
365 }
366 return ret;
367}
368
393template <bool Jacobian, typename T, typename L, typename U>
394inline auto lub_constrain(const T& x, const L& lb, const U& ub,
396 if (Jacobian) {
397 return lub_constrain(x, lb, ub, lp);
398 } else {
399 return lub_constrain(x, lb, ub);
400 }
401}
402
403} // namespace math
404} // namespace stan
405
406#endif
#define unlikely(x)
require_all_t< is_eigen< std::decay_t< Types > >... > require_all_eigen_t
Require all of the types satisfy is_eigen.
Definition is_eigen.hpp:65
subtraction_< as_operation_cl_t< T_a >, as_operation_cl_t< T_b > > subtract(T_a &&a, T_b &&b)
addition_< as_operation_cl_t< T_a >, as_operation_cl_t< T_b > > add(T_a &&a, T_b &&b)
require_all_t< is_stan_scalar< std::decay_t< Types > >... > require_all_stan_scalar_t
Require all of the types satisfy is_stan_scalar.
require_t< is_stan_scalar< std::decay_t< T > > > require_stan_scalar_t
Require type satisfies is_stan_scalar.
require_not_t< is_std_vector< std::decay_t< T > > > require_not_std_vector_t
Require type does not satisfy is_std_vector.
require_all_not_t< is_std_vector< std::decay_t< Types > >... > require_all_not_std_vector_t
Require none of the types satisfy is_std_vector.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
require_not_t< is_var< std::decay_t< T > > > require_not_var_t
Require type does not satisfy is_var.
Definition is_var.hpp:29
fvar< T > abs(const fvar< T > &x)
Definition abs.hpp:15
typename promote_scalar_type< std::decay_t< T >, std::decay_t< S > >::type promote_scalar_t
T eval(T &&arg)
Inputs which have a plain_type equal to the own time are forwarded unmodified (for Eigen expressions ...
Definition eval.hpp:20
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
fvar< T > log(const fvar< T > &x)
Definition log.hpp:15
static constexpr double NEGATIVE_INFTY
Negative infinity.
Definition constants.hpp:51
auto multiply(const Mat1 &m1, const Mat2 &m2)
Return the product of the specified matrices.
Definition multiply.hpp:18
void check_matching_dims(const char *function, const char *name1, const T1 &y1, const char *name2, const T2 &y2)
Check if the two containers have the same dimensions.
fvar< T > log1p_exp(const fvar< T > &x)
Definition log1p_exp.hpp:13
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:17
auto lb_constrain(T &&x, L &&lb)
Return the lower-bounded value for the specified unconstrained input and specified lower bound.
auto ub_constrain(T &&x, U &&ub)
Return the upper-bounded value for the specified unconstrained matrix and upper bound.
matrix_cl< double > lub_constrain(const T &x, const L &lb, const U &ub)
Return the lower and upper-bounded matrix derived by transforming the specified free matrix given the...
void check_less(const char *function, const char *name, const T_y &y, const T_high &high, Idxs... idxs)
Throw an exception if y is not strictly less than high.
fvar< T > inv_logit(const fvar< T > &x)
Returns the inverse logit function applied to the argument.
Definition inv_logit.hpp:20
auto identity_constrain(T &&x, Types &&...)
Returns the result of applying the identity constraint transform to the input.
static constexpr double INFTY
Positive infinity.
Definition constants.hpp:46
typename plain_type< T >::type plain_type_t
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Definition fvar.hpp:9