1#ifndef STAN_MATH_REV_CONSTRAINT_UB_CONSTRAIN_HPP
2#define STAN_MATH_REV_CONSTRAINT_UB_CONSTRAIN_HPP
29template <
typename T,
typename U, require_all_stan_scalar_t<T, U>* =
nullptr,
30 require_any_var_t<T, U>* =
nullptr>
36 if (!is_constant<T>::value && !is_constant<U>::value) {
37 auto neg_exp_x = -std::exp(
value_of(x));
40 [arena_x =
var(x), arena_ub =
var(ub), neg_exp_x](
auto& vi)
mutable {
41 const auto vi_adj = vi.adj();
42 arena_x.adj() += vi_adj * neg_exp_x;
43 arena_ub.adj() += vi_adj;
45 }
else if (!is_constant<T>::value) {
46 auto neg_exp_x = -std::exp(
value_of(x));
48 [arena_x =
var(x), neg_exp_x](
auto& vi)
mutable {
49 arena_x.adj() += vi.adj() * neg_exp_x;
53 [arena_ub =
var(ub)](
auto& vi)
mutable {
54 arena_ub.adj() += vi.adj();
80template <
typename T,
typename U, require_all_stan_scalar_t<T, U>* =
nullptr,
81 require_any_var_t<T, U>* =
nullptr>
82inline auto ub_constrain(
const T& x,
const U& ub, return_type_t<T, U>& lp) {
84 const bool is_ub_inf = ub_val ==
INFTY;
85 if (!is_constant<T>::value && !is_constant<U>::value) {
90 auto neg_exp_x = -std::exp(
value_of(x));
92 [lp, arena_x =
var(x), arena_ub =
var(ub),
93 neg_exp_x](
auto& vi)
mutable {
94 const auto vi_adj = vi.adj();
95 arena_x.adj() += vi_adj * neg_exp_x + lp.adj();
96 arena_ub.adj() += vi_adj;
99 }
else if (!is_constant<T>::value) {
104 auto neg_exp_x = -std::exp(
value_of(x));
107 [lp, arena_x =
var(x), neg_exp_x](
auto& vi)
mutable {
108 arena_x.adj() += vi.adj() * neg_exp_x + lp.adj();
117 [arena_ub =
var(ub)](
auto& vi)
mutable {
118 arena_ub.adj() += vi.adj();
135template <
typename T,
typename U, require_matrix_t<T>* =
nullptr,
136 require_stan_scalar_t<U>* =
nullptr,
137 require_any_st_var<T, U>* =
nullptr>
139 using ret_type = return_var_matrix_t<T, T, U>;
144 if (!is_constant<T>::value && !is_constant<U>::value) {
145 arena_t<promote_scalar_t<var, T>> arena_x = x;
146 auto arena_neg_exp_x =
to_arena(-arena_x.val().array().exp());
147 arena_t<ret_type> ret = ub_val + arena_neg_exp_x;
149 [arena_x, arena_neg_exp_x, ret, arena_ub =
var(ub)]()
mutable {
150 arena_x.adj().array() += ret.adj().array() * arena_neg_exp_x;
151 arena_ub.adj() += ret.adj().sum();
153 return ret_type(ret);
154 }
else if (!is_constant<T>::value) {
155 arena_t<promote_scalar_t<var, T>> arena_x = x;
156 auto arena_neg_exp_x =
to_arena(-arena_x.val().array().exp());
157 arena_t<ret_type> ret = ub_val + arena_neg_exp_x;
159 arena_x.adj().array() += ret.adj().array() * arena_neg_exp_x;
161 return ret_type(ret);
163 arena_t<ret_type> ret = ub_val -
value_of(x).array().exp();
165 arena_ub.adj() += ret.adj().sum();
167 return ret_type(ret);
184template <
typename T,
typename U, require_matrix_t<T>* =
nullptr,
185 require_stan_scalar_t<U>* =
nullptr,
186 require_any_st_var<T, U>* =
nullptr>
195 auto arena_neg_exp_x =
to_arena(-arena_x.val().array().exp());
197 lp += arena_x.val().sum();
199 arena_ub =
var(ub)]()
mutable {
200 arena_x.adj().array() += ret.adj().array() * arena_neg_exp_x + lp.adj();
201 arena_ub.adj() += ret.adj().sum();
203 return ret_type(ret);
206 auto arena_neg_exp_x =
to_arena(-arena_x.val().array().exp());
208 lp += arena_x.val().sum();
210 arena_x.adj().array() += ret.adj().array() * arena_neg_exp_x + lp.adj();
212 return ret_type(ret);
218 arena_ub.adj() += ret.adj().sum();
220 return ret_type(ret);
237template <
typename T,
typename U, require_all_matrix_t<T, U>* =
nullptr,
238 require_any_st_var<T, U>* =
nullptr>
245 auto ub_val =
to_ref(arena_ub.val());
247 auto neg_exp_x =
to_arena(-arena_x.val().array().exp());
250 .
select(ub_val.array() + neg_exp_x, arena_x.val().array());
252 is_not_inf_ub]()
mutable {
253 arena_x.adj().array()
255 .
select(ret.adj().array() * neg_exp_x, ret.adj().array());
256 arena_ub.adj().array() += (is_not_inf_ub).
select(ret.adj().array(), 0.0);
258 return ret_type(ret);
259 }
else if (!is_constant<T>::value) {
260 arena_t<promote_scalar_t<var, T>> arena_x = x;
263 auto neg_exp_x =
to_arena(-arena_x.val().array().exp());
264 arena_t<ret_type> ret
266 .
select(ub_val.array() + neg_exp_x, arena_x.val().array());
268 arena_x.adj().array()
270 .
select(ret.adj().array() * neg_exp_x, ret.adj().array());
272 return ret_type(ret);
274 arena_t<promote_scalar_t<var, U>> arena_ub =
to_arena(ub);
276 =
to_arena((arena_ub.val().array() !=
INFTY).template cast<double>());
278 arena_t<ret_type> ret
279 = (is_not_inf_ub).
select(arena_ub.val().array() - x_ref.exp(), x_ref);
281 arena_ub.adj().array() += ret.adj().array() * is_not_inf_ub;
283 return ret_type(ret);
300template <
typename T,
typename U, require_all_matrix_t<T, U>* =
nullptr,
301 require_any_st_var<T, U>* =
nullptr>
302inline auto ub_constrain(
const T& x,
const U& ub, return_type_t<T, U>& lp) {
304 using ret_type = return_var_matrix_t<T, T, U>;
305 if (!is_constant<T>::value && !is_constant<U>::value) {
306 arena_t<promote_scalar_t<var, T>> arena_x = x;
307 arena_t<promote_scalar_t<var, U>> arena_ub = ub;
308 auto ub_val =
to_ref(arena_ub.val());
310 auto neg_exp_x =
to_arena(-arena_x.val().array().exp());
311 arena_t<ret_type> ret
313 .
select(ub_val.array() + neg_exp_x, arena_x.val().array());
314 lp += (is_not_inf_ub).
select(arena_x.val().array(), 0).
sum();
316 is_not_inf_ub]()
mutable {
317 arena_x.adj().array()
319 .
select(ret.adj().array() * neg_exp_x + lp.adj(),
321 arena_ub.adj().array() += (is_not_inf_ub).
select(ret.adj().array(), 0.0);
323 return ret_type(ret);
324 }
else if (!is_constant<T>::value) {
325 arena_t<promote_scalar_t<var, T>> arena_x = x;
328 auto neg_exp_x =
to_arena(-arena_x.val().array().exp());
329 arena_t<ret_type> ret
331 .
select(ub_val.array() + neg_exp_x, arena_x.val().array());
332 lp += (is_not_inf_ub).
select(arena_x.val().array(), 0).
sum();
334 [arena_x, neg_exp_x, ret, lp, is_not_inf_ub]()
mutable {
335 arena_x.adj().array()
337 .
select(ret.adj().array() * neg_exp_x + lp.adj(),
340 return ret_type(ret);
342 arena_t<promote_scalar_t<var, U>> arena_ub =
to_arena(ub);
344 =
to_arena((arena_ub.val().array() !=
INFTY).template cast<double>());
346 arena_t<ret_type> ret
347 = (is_not_inf_ub).
select(arena_ub.val().array() - x_ref.exp(), x_ref);
348 lp += (is_not_inf_ub).
select(x_ref, 0).sum();
350 arena_ub.adj().array() += ret.adj().array() * is_not_inf_ub;
352 return ret_type(ret);
select_< as_operation_cl_t< T_condition >, as_operation_cl_t< T_then >, as_operation_cl_t< T_else > > select(T_condition &&condition, T_then &&then, T_else &&els)
Selection operation on kernel generator expressions.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
var_value< plain_type_t< T > > make_callback_var(T &&value, F &&functor)
Creates a new var initialized with a callback_vari with a given value and reverse-pass callback funct...
void reverse_pass_callback(F &&functor)
Puts a callback on the autodiff stack to be called in reverse pass.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
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.
arena_t< T > to_arena(const T &a)
Converts given argument into a type that either has any dynamic allocation on AD stack or schedules i...
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
auto sum(const std::vector< T > &m)
Return the sum of the entries of the specified standard vector.
auto ub_constrain(T &&x, U &&ub)
Return the upper-bounded value for the specified unconstrained matrix and upper bound.
auto identity_constrain(T &&x, Types &&...)
Returns the result of applying the identity constraint transform to the input.
static constexpr double INFTY
Positive infinity.
typename internal::arena_type_impl< std::decay_t< T > >::type arena_t
Determines a type that can be used in place of T that does any dynamic allocations on the AD stack.
std::conditional_t< is_any_var_matrix< ReturnType, Types... >::value, stan::math::var_value< stan::math::promote_scalar_t< double, plain_type_t< ReturnType > > >, stan::math::promote_scalar_t< stan::math::var_value< double >, plain_type_t< ReturnType > > > return_var_matrix_t
Given an Eigen type and several inputs, determine if a matrix should be var<Matrix> or Matrix<var>.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Metaprogramming struct to detect whether a given type is constant in the mathematical sense (not the ...