Automatic Differentiation
 
Loading...
Searching...
No Matches
lub_constrain.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_REV_CONSTRAINT_LUB_CONSTRAIN_HPP
2#define STAN_MATH_REV_CONSTRAINT_LUB_CONSTRAIN_HPP
3
9#include <cmath>
10
11namespace stan {
12namespace math {
13
33template <typename T, typename L, typename U,
34 require_all_stan_scalar_t<T, L, U>* = nullptr,
35 require_var_t<return_type_t<T, L, U>>* = nullptr>
36inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
37 using std::exp;
38 const auto lb_val = value_of(lb);
39 const auto ub_val = value_of(ub);
40 const bool is_lb_inf = lb_val == NEGATIVE_INFTY;
41 const bool is_ub_inf = ub_val == INFTY;
42 if (unlikely(is_ub_inf && is_lb_inf)) {
43 return identity_constrain(x, ub, lb);
44 } else if (unlikely(is_ub_inf)) {
45 return lb_constrain(identity_constrain(x, ub), lb);
46 } else if (unlikely(is_lb_inf)) {
47 return ub_constrain(identity_constrain(x, lb), ub);
48 } else {
49 check_less("lub_constrain", "lb", lb_val, ub_val);
50 auto diff = ub_val - lb_val;
51 double inv_logit_x = inv_logit(value_of(x));
52 return make_callback_var(diff * inv_logit_x + lb_val,
53 [x, ub, lb, diff, inv_logit_x](auto& vi) mutable {
54 if constexpr (is_autodiff_v<T>) {
55 x.adj() += vi.adj() * diff * inv_logit_x
56 * (1.0 - inv_logit_x);
57 }
58 if constexpr (is_autodiff_v<L>) {
59 lb.adj() += vi.adj() * (1.0 - inv_logit_x);
60 }
61 if constexpr (is_autodiff_v<U>) {
62 ub.adj() += vi.adj() * inv_logit_x;
63 }
64 });
65 }
66}
67
101template <typename T, typename L, typename U,
102 require_all_stan_scalar_t<T, L, U>* = nullptr,
103 require_var_t<return_type_t<T, L, U>>* = nullptr>
104inline auto lub_constrain(const T& x, const L& lb, const U& ub,
105 return_type_t<T, L, U>& lp) {
106 using std::exp;
107 const auto lb_val = value_of(lb);
108 const auto ub_val = value_of(ub);
109 const bool is_lb_inf = lb_val == NEGATIVE_INFTY;
110 const bool is_ub_inf = ub_val == INFTY;
111 if (unlikely(is_ub_inf && is_lb_inf)) {
112 return identity_constrain(x, ub, lb);
113 } else if (unlikely(is_ub_inf)) {
114 return lb_constrain(identity_constrain(x, ub), lb, lp);
115 } else if (unlikely(is_lb_inf)) {
116 return ub_constrain(identity_constrain(x, lb), ub, lp);
117 } else {
118 check_less("lub_constrain", "lb", lb_val, ub_val);
119 auto neg_abs_x = -abs(value_of(x));
120 auto diff = ub_val - lb_val;
121 double inv_logit_x = inv_logit(value_of(x));
122 lp += (log(diff) + (neg_abs_x - (2.0 * log1p_exp(neg_abs_x))));
123 return make_callback_var(
124 diff * inv_logit_x + lb_val,
125 [x, ub, lb, diff, lp, inv_logit_x](auto& vi) mutable {
126 if constexpr (is_autodiff_v<T>) {
127 x.adj() += vi.adj() * diff * inv_logit_x * (1.0 - inv_logit_x)
128 + lp.adj() * (1.0 - 2.0 * inv_logit_x);
129 }
130 if constexpr (is_autodiff_v<L> && is_autodiff_v<U>) {
131 const auto one_over_diff = 1.0 / diff;
132 lb.adj()
133 += vi.adj() * (1.0 - inv_logit_x) + -one_over_diff * lp.adj();
134 ub.adj() += vi.adj() * inv_logit_x + one_over_diff * lp.adj();
135 } else if constexpr (is_autodiff_v<L>) {
136 lb.adj()
137 += vi.adj() * (1.0 - inv_logit_x) + (-1.0 / diff) * lp.adj();
138 } else if constexpr (is_autodiff_v<U>) {
139 ub.adj() += vi.adj() * inv_logit_x + (1.0 / diff) * lp.adj();
140 }
141 });
142 }
143}
144
148template <typename T, typename L, typename U, require_matrix_t<T>* = nullptr,
149 require_all_stan_scalar_t<L, U>* = nullptr,
150 require_var_t<return_type_t<T, L, U>>* = nullptr>
151inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
152 using std::exp;
153 using ret_type = return_var_matrix_t<T, T, L, U>;
154 const auto lb_val = value_of(lb);
155 const auto ub_val = value_of(ub);
156 const bool is_lb_inf = lb_val == NEGATIVE_INFTY;
157 const bool is_ub_inf = ub_val == INFTY;
158 if (unlikely(is_ub_inf && is_lb_inf)) {
159 return ret_type(identity_constrain(x, ub, lb));
160 } else if (unlikely(is_ub_inf)) {
161 return ret_type(lb_constrain(identity_constrain(x, ub), lb));
162 } else if (unlikely(is_lb_inf)) {
163 return ret_type(ub_constrain(identity_constrain(x, lb), ub));
164 } else {
165 arena_t<T> arena_x = x;
166 check_less("lub_constrain", "lb", lb_val, ub_val);
167 const auto diff = ub_val - lb_val;
168 auto inv_logit_x = to_arena(inv_logit(arena_x.val().array()));
169 arena_t<ret_type> ret = diff * inv_logit_x + lb_val;
170 reverse_pass_callback([arena_x, ub, lb, ret, diff, inv_logit_x]() mutable {
171 if constexpr (is_autodiff_v<T>) {
172 arena_x.adj().array()
173 += ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x);
174 }
175 if constexpr (is_autodiff_v<L>) {
176 lb.adj() += (ret.adj().array() * (1.0 - inv_logit_x)).sum();
177 }
178 if constexpr (is_autodiff_v<U>) {
179 ub.adj() += (ret.adj().array() * inv_logit_x).sum();
180 }
181 });
182 return ret_type(ret);
183 }
184}
185
189template <typename T, typename L, typename U, require_matrix_t<T>* = nullptr,
190 require_all_stan_scalar_t<L, U>* = nullptr,
191 require_var_t<return_type_t<T, L, U>>* = nullptr>
192inline auto lub_constrain(const T& x, const L& lb, const U& ub,
194 using std::exp;
195 using ret_type = return_var_matrix_t<T, T, L, U>;
196 const auto lb_val = value_of(lb);
197 const auto ub_val = value_of(ub);
198 const bool is_lb_inf = lb_val == NEGATIVE_INFTY;
199 const bool is_ub_inf = ub_val == INFTY;
200 if (unlikely(is_ub_inf && is_lb_inf)) {
201 return ret_type(identity_constrain(x, ub, lb));
202 } else if (unlikely(is_ub_inf)) {
203 return ret_type(lb_constrain(identity_constrain(x, ub), lb, lp));
204 } else if (unlikely(is_lb_inf)) {
205 return ret_type(ub_constrain(identity_constrain(x, lb), ub, lp));
206 } else {
207 check_less("lub_constrain", "lb", lb_val, ub_val);
208 arena_t<T> arena_x = x;
209 auto neg_abs_x = to_arena(-(value_of(arena_x).array()).abs());
210 auto diff = ub_val - lb_val;
211 lp += (log(diff) + (neg_abs_x - (2.0 * log1p_exp(neg_abs_x)))).sum();
212 auto inv_logit_x = to_arena(inv_logit(value_of(arena_x).array()));
213 arena_t<ret_type> ret = diff * inv_logit_x + lb_val;
215 [arena_x, ub, lb, ret, lp, diff, inv_logit_x]() mutable {
216 if constexpr (is_autodiff_v<T>) {
217 arena_x.adj().array()
218 += ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x)
219 + lp.adj() * (1.0 - 2.0 * inv_logit_x);
220 }
221 if constexpr (is_autodiff_v<L> && is_autodiff_v<U>) {
222 const auto lp_calc = lp.adj() * ret.size();
223 const auto one_over_diff = 1.0 / diff;
224 lb.adj() += (ret.adj().array() * (1.0 - inv_logit_x)).sum()
225 + -one_over_diff * lp_calc;
226 ub.adj() += (ret.adj().array() * inv_logit_x).sum()
227 + one_over_diff * lp_calc;
228 } else if constexpr (is_autodiff_v<L>) {
229 lb.adj() += (ret.adj().array() * (1.0 - inv_logit_x)).sum()
230 + -(1.0 / diff) * lp.adj() * ret.size();
231 } else if constexpr (is_autodiff_v<U>) {
232 ub.adj() += (ret.adj().array() * inv_logit_x).sum()
233 + (1.0 / diff) * lp.adj() * ret.size();
234 }
235 });
236 return ret_type(ret);
237 }
238}
239
244template <typename T, typename L, typename U,
246 require_stan_scalar_t<U>* = nullptr,
248inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
249 using std::exp;
250 using ret_type = return_var_matrix_t<T, T, L, U>;
251 const auto ub_val = value_of(ub);
252 const bool is_ub_inf = ub_val == INFTY;
253 if (unlikely(is_ub_inf)) {
254 return eval(lb_constrain(identity_constrain(x, ub), lb));
255 } else {
256 arena_t<T> arena_x = x;
257 arena_t<L> arena_lb = lb;
258 const auto lb_val = value_of(arena_lb).array().eval();
259 check_less("lub_constrain", "lb", lb_val, ub_val);
260 auto is_lb_inf = to_arena((lb_val == NEGATIVE_INFTY));
261 auto diff = to_arena(ub_val - lb_val);
262 auto inv_logit_x = to_arena(inv_logit(value_of(arena_x).array()));
263 arena_t<ret_type> ret = (is_lb_inf).select(
264 ub_val - value_of(arena_x).array().exp(), diff * inv_logit_x + lb_val);
265 reverse_pass_callback([arena_x, ub, arena_lb, ret, diff, inv_logit_x,
266 is_lb_inf]() mutable {
267 if constexpr (is_autodiff_v<T>) {
268 arena_x.adj().array() += (is_lb_inf).select(
269 ret.adj().array() * -value_of(arena_x).array().exp(),
270 ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x));
271 }
272 if constexpr (is_autodiff_v<U>) {
273 ub.adj()
274 += (is_lb_inf)
275 .select(ret.adj().array(), ret.adj().array() * inv_logit_x)
276 .sum();
277 }
278 if constexpr (is_autodiff_v<L>) {
279 arena_lb.adj().array()
280 += (is_lb_inf).select(0, ret.adj().array() * (1.0 - inv_logit_x));
281 }
282 });
283 return ret_type(ret);
284 }
285}
286
291template <typename T, typename L, typename U,
292 require_all_matrix_t<T, L>* = nullptr,
293 require_stan_scalar_t<U>* = nullptr,
294 require_var_t<return_type_t<T, L, U>>* = nullptr>
295inline auto lub_constrain(const T& x, const L& lb, const U& ub,
296 std::decay_t<return_type_t<T, L, U>>& lp) {
297 using std::exp;
298 using ret_type = return_var_matrix_t<T, T, L, U>;
299 const auto ub_val = value_of(ub);
300 const bool is_ub_inf = ub_val == INFTY;
301 if (unlikely(is_ub_inf)) {
302 return ret_type(lb_constrain(identity_constrain(x, ub), lb, lp));
303 } else {
304 arena_t<T> arena_x = x;
305 arena_t<L> arena_lb = lb;
306 const auto arena_x_val = to_arena(value_of(arena_x).array());
307 const auto lb_val = value_of(arena_lb).array().eval();
308 check_less("lub_constrain", "lb", lb_val, ub_val);
309 auto is_lb_inf = to_arena((lb_val == NEGATIVE_INFTY));
310 auto diff = to_arena(ub_val - lb_val);
311 auto neg_abs_x = to_arena(-arena_x_val.abs());
312 auto inv_logit_x = to_arena(inv_logit(arena_x_val));
313 arena_t<ret_type> ret = (is_lb_inf).select(ub_val - arena_x_val.exp(),
314 diff * inv_logit_x + lb_val);
315 lp += (is_lb_inf)
316 .select(arena_x_val,
317 log(diff) + (neg_abs_x - (2.0 * log1p_exp(neg_abs_x))))
318 .sum();
319 reverse_pass_callback([arena_x, arena_x_val, ub, arena_lb, ret, lp, diff,
320 inv_logit_x, is_lb_inf]() mutable {
321 const auto lp_adj = lp.adj();
322 if constexpr (is_autodiff_v<T>) {
323 const auto x_sign = arena_x_val.sign().eval();
324 arena_x.adj().array() += (is_lb_inf).select(
325 ret.adj().array() * -arena_x_val.exp() + lp_adj,
326 ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x)
327 + lp.adj() * (1.0 - 2.0 * inv_logit_x));
328 }
329 if constexpr (is_autodiff_v<L>) {
330 arena_lb.adj().array()
331 += (is_lb_inf).select(0, ret.adj().array() * (1.0 - inv_logit_x)
332 + -(1.0 / diff) * lp_adj);
333 }
334 if constexpr (is_autodiff_v<U>) {
335 ub.adj()
336 += (is_lb_inf)
337 .select(ret.adj().array(), ret.adj().array() * inv_logit_x
338 + (1.0 / diff) * lp_adj)
339 .sum();
340 }
341 });
342 return ret_type(ret);
343 }
344}
345
350template <typename T, typename L, typename U,
352 require_stan_scalar_t<L>* = nullptr,
354inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
355 using std::exp;
356 using ret_type = return_var_matrix_t<T, T, L, U>;
357 const auto lb_val = value_of(lb);
358 const bool is_lb_inf = lb_val == NEGATIVE_INFTY;
359 if (unlikely(is_lb_inf)) {
360 return eval(ub_constrain(identity_constrain(x, lb), ub));
361 } else {
362 arena_t<T> arena_x = x;
363 auto arena_x_val = to_arena(value_of(arena_x));
364 arena_t<U> arena_ub = ub;
365 const auto ub_val = value_of(arena_ub).array().eval();
366 check_less("lub_constrain", "lb", lb_val, ub_val);
367 auto is_ub_inf = to_arena((ub_val == INFTY));
368 auto diff = to_arena(ub_val - lb_val);
369 auto inv_logit_x = to_arena(inv_logit(arena_x_val.array()));
370 arena_t<ret_type> ret = (is_ub_inf).select(
371 arena_x_val.array().exp() + lb_val, diff * inv_logit_x + lb_val);
372 reverse_pass_callback([arena_x, arena_x_val, arena_ub, lb, ret, is_ub_inf,
373 inv_logit_x, diff]() mutable {
374 if constexpr (is_autodiff_v<T>) {
375 arena_x.adj().array() += (is_ub_inf).select(
376 ret.adj().array() * arena_x_val.array().exp(),
377 ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x));
378 }
379 if constexpr (is_autodiff_v<L>) {
380 lb.adj() += (is_ub_inf)
381 .select(ret.adj().array(),
382 ret.adj().array() * (1.0 - inv_logit_x))
383 .sum();
384 }
385 if constexpr (is_autodiff_v<U>) {
386 arena_ub.adj().array()
387 += (is_ub_inf).select(0, ret.adj().array() * inv_logit_x);
388 }
389 });
390 return ret_type(ret);
391 }
392}
393
398template <typename T, typename L, typename U,
399 require_all_matrix_t<T, U>* = nullptr,
400 require_stan_scalar_t<L>* = nullptr,
401 require_var_t<return_type_t<T, L, U>>* = nullptr>
402inline auto lub_constrain(const T& x, const L& lb, const U& ub,
403 std::decay_t<return_type_t<T, L, U>>& lp) {
404 using std::exp;
405 using ret_type = return_var_matrix_t<T, T, L, U>;
406 const auto lb_val = value_of(lb);
407 const bool is_lb_inf = lb_val == NEGATIVE_INFTY;
408 if (unlikely(is_lb_inf)) {
409 return eval(ub_constrain(identity_constrain(x, lb), ub, lp));
410 } else {
411 arena_t<T> arena_x = x;
412 auto arena_x_val = to_arena(value_of(arena_x));
413 arena_t<U> arena_ub = ub;
414 const auto& ub_val = to_ref(value_of(arena_ub));
415 check_less("lub_constrain", "lb", lb_val, ub_val);
416 auto is_ub_inf = to_arena((ub_val.array() == INFTY));
417 auto diff = to_arena(ub_val.array() - lb_val);
418 auto neg_abs_x = to_arena(-(arena_x_val.array()).abs());
419 lp += (is_ub_inf)
420 .select(arena_x_val.array(),
421 log(diff) + (neg_abs_x - (2.0 * log1p_exp(neg_abs_x))))
422 .sum();
423 auto inv_logit_x = to_arena(inv_logit(arena_x_val.array()));
424 arena_t<ret_type> ret = (is_ub_inf).select(
425 arena_x_val.array().exp() + lb_val, diff * inv_logit_x + lb_val);
426 reverse_pass_callback([arena_x, arena_x_val, diff, inv_logit_x, arena_ub,
427 lb, ret, lp, is_ub_inf]() mutable {
428 const auto lp_adj = lp.adj();
429 if constexpr (is_autodiff_v<T>) {
430 arena_x.adj().array() += (is_ub_inf).select(
431 ret.adj().array() * arena_x_val.array().exp() + lp_adj,
432 ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x)
433 + lp.adj() * (1.0 - 2.0 * inv_logit_x));
434 }
435 if constexpr (is_autodiff_v<L>) {
436 lb.adj() += (is_ub_inf)
437 .select(ret.adj().array(),
438 ret.adj().array() * (1.0 - inv_logit_x)
439 + -(1.0 / diff) * lp_adj)
440 .sum();
441 }
442 if constexpr (is_autodiff_v<U>) {
443 arena_ub.adj().array() += (is_ub_inf).select(
444 0, ret.adj().array() * inv_logit_x + (1.0 / diff) * lp_adj);
445 }
446 });
447 return ret_type(ret);
448 }
449}
450
454template <typename T, typename L, typename U,
455 require_all_matrix_t<T, L, U>* = nullptr,
456 require_var_t<return_type_t<T, L, U>>* = nullptr>
457inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
458 using std::exp;
459 using ret_type = return_var_matrix_t<T, T, L, U>;
460 arena_t<T> arena_x = x;
461 auto arena_x_val = value_of(arena_x);
462 arena_t<L> arena_lb = lb;
463 arena_t<U> arena_ub = ub;
464 auto lb_val = value_of(arena_lb).array();
465 auto ub_val = value_of(arena_ub).array();
466 check_less("lub_constrain", "lb", lb_val, ub_val);
467 auto inv_logit_x = to_arena(inv_logit(arena_x_val.array()));
468 auto is_lb_inf = to_arena((lb_val == NEGATIVE_INFTY));
469 auto is_ub_inf = to_arena((ub_val == INFTY));
470 auto is_lb_ub_inf = to_arena(is_lb_inf && is_ub_inf);
471 auto diff = to_arena(ub_val - lb_val);
472 // if both, identity, then lb_inf -> ub_constrain, then ub_inf -> lb_constrain
473 arena_t<ret_type> ret
474 = (is_lb_ub_inf)
475 .select(arena_x_val.array(),
476 (is_lb_inf).select(
477 ub_val - arena_x.val().array().exp(),
478 (is_ub_inf).select(arena_x_val.array().exp() + lb_val,
479 diff * inv_logit_x + lb_val)));
480 reverse_pass_callback([arena_x, arena_x_val, inv_logit_x, arena_ub, arena_lb,
481 diff, ret, is_ub_inf, is_lb_inf,
482 is_lb_ub_inf]() mutable {
483 // The most likely case is neither of them are infinity
484 const bool is_none_inf = !(is_lb_inf.any() || is_ub_inf.any());
485 if (is_none_inf) {
486 if constexpr (is_autodiff_v<T>) {
487 arena_x.adj().array()
488 += ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x);
489 }
490 if constexpr (is_autodiff_v<L>) {
491 arena_lb.adj().array() += ret.adj().array() * (1.0 - inv_logit_x);
492 }
493 if constexpr (is_autodiff_v<U>) {
494 arena_ub.adj().array() += ret.adj().array() * inv_logit_x;
495 }
496 } else {
497 if constexpr (is_autodiff_v<T>) {
498 arena_x.adj().array()
499 += (is_lb_ub_inf)
500 .select(
501 ret.adj().array(),
502 (is_lb_inf).select(
503 ret.adj().array() * -arena_x_val.array().exp(),
504 (is_ub_inf).select(
505 ret.adj().array() * arena_x_val.array().exp(),
506 ret.adj().array() * diff * inv_logit_x
507 * (1.0 - inv_logit_x))));
508 }
509 if constexpr (is_autodiff_v<U>) {
510 arena_ub.adj().array() += (is_ub_inf).select(
511 0, (is_lb_inf).select(ret.adj().array(),
512 ret.adj().array() * inv_logit_x));
513 }
514 if constexpr (is_autodiff_v<L>) {
515 arena_lb.adj().array() += (is_lb_inf).select(
516 0, (is_ub_inf).select(ret.adj().array(),
517 ret.adj().array() * (1.0 - inv_logit_x)));
518 }
519 }
520 });
521 return ret_type(ret);
522}
523
527template <typename T, typename L, typename U,
528 require_all_matrix_t<T, L, U>* = nullptr,
529 require_var_t<return_type_t<T, L, U>>* = nullptr>
530inline auto lub_constrain(const T& x, const L& lb, const U& ub,
531 return_type_t<T, L, U>& lp) {
532 using std::exp;
533 using ret_type = return_var_matrix_t<T, T, L, U>;
534 arena_t<T> arena_x = x;
535 auto arena_x_val = value_of(arena_x);
536 arena_t<L> arena_lb = lb;
537 arena_t<U> arena_ub = ub;
538 auto lb_val = value_of(arena_lb).array();
539 auto ub_val = value_of(arena_ub).array();
540 check_less("lub_constrain", "lb", lb_val, ub_val);
541 auto inv_logit_x = to_arena(inv_logit(arena_x_val.array()));
542 auto is_lb_inf = to_arena((lb_val == NEGATIVE_INFTY));
543 auto is_ub_inf = to_arena((ub_val == INFTY));
544 auto is_lb_ub_inf = to_arena(is_lb_inf && is_ub_inf);
545 auto diff = to_arena(ub_val - lb_val);
546 // if both, identity, then lb_inf -> ub_constrain, then ub_inf -> lb_constrain
547 arena_t<ret_type> ret
548 = (is_lb_ub_inf)
549 .select(arena_x_val.array(),
550 (is_lb_inf).select(
551 ub_val - arena_x.val().array().exp(),
552 (is_ub_inf).select(arena_x_val.array().exp() + lb_val,
553 diff * inv_logit_x + lb_val)));
554 auto neg_abs_x = to_arena(-(arena_x_val.array()).abs());
555 lp += (is_lb_ub_inf)
556 .select(
557 0,
558 (is_lb_inf || is_ub_inf)
559 .select(
560 arena_x_val.array(),
561 log(diff) + (neg_abs_x - (2.0 * log1p_exp(neg_abs_x)))))
562 .sum();
563 reverse_pass_callback([arena_x, arena_x_val, inv_logit_x, arena_ub, arena_lb,
564 diff, ret, is_ub_inf, is_lb_inf, is_lb_ub_inf,
565 lp]() mutable {
566 const auto lp_adj = lp.adj();
567 // The most likely case is neither of them are infinity
568 const bool is_none_inf = !(is_lb_inf.any() || is_ub_inf.any());
569 if (is_none_inf) {
570 if constexpr (is_autodiff_v<T>) {
571 arena_x.adj().array()
572 += ret.adj().array() * diff * inv_logit_x * (1.0 - inv_logit_x)
573 + lp.adj() * (1.0 - 2.0 * inv_logit_x);
574 }
575 if constexpr (is_autodiff_v<L>) {
576 arena_lb.adj().array()
577 += ret.adj().array() * (1.0 - inv_logit_x) + -(1.0 / diff) * lp_adj;
578 }
579 if constexpr (is_autodiff_v<U>) {
580 arena_ub.adj().array()
581 += ret.adj().array() * inv_logit_x + (1.0 / diff) * lp_adj;
582 }
583 } else {
584 if constexpr (is_autodiff_v<T>) {
585 arena_x.adj().array()
586 += (is_lb_ub_inf)
587 .select(
588 ret.adj().array(),
589 (is_lb_inf).select(
590 ret.adj().array() * -arena_x_val.array().exp()
591 + lp_adj,
592 (is_ub_inf).select(
593 ret.adj().array() * arena_x_val.array().exp()
594 + lp_adj,
595 ret.adj().array() * diff * inv_logit_x
596 * (1.0 - inv_logit_x)
597 + lp.adj() * (1.0 - 2.0 * inv_logit_x))));
598 }
599 if constexpr (is_autodiff_v<L>) {
600 arena_lb.adj().array() += (is_lb_inf).select(
601 0, (is_ub_inf).select(ret.adj().array(),
602 ret.adj().array() * (1.0 - inv_logit_x)
603 + -(1.0 / diff) * lp_adj));
604 }
605 if constexpr (is_autodiff_v<U>) {
606 arena_ub.adj().array() += (is_ub_inf).select(
607 0, (is_lb_inf).select(
608 ret.adj().array(),
609 ret.adj().array() * inv_logit_x + (1.0 / diff) * lp_adj));
610 }
611 }
612 });
613 return ret_type(ret);
614}
615
616} // namespace math
617} // namespace stan
618
619#endif
#define unlikely(x)
require_all_t< is_matrix< std::decay_t< Types > >... > require_all_matrix_t
Require all of the types satisfy is_matrix.
Definition is_matrix.hpp:38
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.
Definition select.hpp:148
require_t< is_stan_scalar< std::decay_t< T > > > require_stan_scalar_t
Require type satisfies is_stan_scalar.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
require_t< is_var< std::decay_t< T > > > require_var_t
Require type satisfies is_var.
Definition is_var.hpp:89
auto diff(F &&f, Theta &&theta, const Eigen::Index hessian_block_size, Stream *msgs, Args &&... args)
Computes theta gradient and negative block diagonal Hessian of f wrt theta and args....
fvar< T > abs(const fvar< T > &x)
Definition abs.hpp:15
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 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:18
auto inv_logit(T &&x)
Returns the inverse logit function applied to the argument.
Definition inv_logit.hpp:20
static constexpr double NEGATIVE_INFTY
Negative infinity.
Definition constants.hpp:51
fvar< T > log1p_exp(const fvar< T > &x)
Definition log1p_exp.hpp:14
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...
Definition to_arena.hpp:25
auto lb_constrain(T &&x, L &&lb)
Return the lower-bounded value for the specified unconstrained input and specified lower bound.
auto sum(const std::vector< T > &m)
Return the sum of the entries of the specified standard vector.
Definition sum.hpp:23
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...
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:18
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.
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 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 ...