1 #ifndef STAN_MATH_REV_FUN_OWENS_T_HPP
2 #define STAN_MATH_REV_FUN_OWENS_T_HPP
3 
4 #include <stan/math/rev/meta.hpp>
5 #include <stan/math/rev/core.hpp>
6 #include <stan/math/prim/fun/constants.hpp>
7 #include <stan/math/prim/fun/erf.hpp>
8 #include <stan/math/prim/fun/owens_t.hpp>
9 #include <stan/math/prim/fun/square.hpp>
10 #include <cmath>
11 
12 namespace stan {
13 namespace math {
14 
15 namespace internal {
16 class owens_t_vv_vari : public op_vv_vari {
17  public:
owens_t_vv_vari(vari * avi,vari * bvi)18   owens_t_vv_vari(vari* avi, vari* bvi)
19       : op_vv_vari(owens_t(avi->val_, bvi->val_), avi, bvi) {}
chain()20   void chain() {
21     const double neg_avi_sq_div_2 = -square(avi_->val_) * 0.5;
22     const double one_p_bvi_sq = 1.0 + square(bvi_->val_);
23 
24     avi_->adj_ += adj_ * erf(bvi_->val_ * avi_->val_ * INV_SQRT_TWO)
25                   * std::exp(neg_avi_sq_div_2) * INV_SQRT_TWO_PI * -0.5;
26     bvi_->adj_ += adj_ * std::exp(neg_avi_sq_div_2 * one_p_bvi_sq)
27                   / (one_p_bvi_sq * TWO_PI);
28   }
29 };
30 
31 class owens_t_vd_vari : public op_vd_vari {
32  public:
owens_t_vd_vari(vari * avi,double b)33   owens_t_vd_vari(vari* avi, double b)
34       : op_vd_vari(owens_t(avi->val_, b), avi, b) {}
chain()35   void chain() {
36     avi_->adj_ += adj_ * erf(bd_ * avi_->val_ * INV_SQRT_TWO)
37                   * std::exp(-square(avi_->val_) * 0.5) * INV_SQRT_TWO_PI
38                   * -0.5;
39   }
40 };
41 
42 class owens_t_dv_vari : public op_dv_vari {
43  public:
owens_t_dv_vari(double a,vari * bvi)44   owens_t_dv_vari(double a, vari* bvi)
45       : op_dv_vari(owens_t(a, bvi->val_), a, bvi) {}
chain()46   void chain() {
47     const double one_p_bvi_sq = 1.0 + square(bvi_->val_);
48     bvi_->adj_ += adj_ * std::exp(-0.5 * square(ad_) * one_p_bvi_sq)
49                   / (one_p_bvi_sq * TWO_PI);
50   }
51 };
52 }  // namespace internal
53 
54 /**
55  * The Owen's T function of h and a.
56  *
57  * Used to compute the cumulative density function for the skew normal
58  * distribution.
59  *
60  * @param h var parameter.
61  * @param a var parameter.
62  * @return The Owen's T function.
63  */
owens_t(const var & h,const var & a)64 inline var owens_t(const var& h, const var& a) {
65   return var(new internal::owens_t_vv_vari(h.vi_, a.vi_));
66 }
67 
68 /**
69  * The Owen's T function of h and a.
70  *
71  * Used to compute the cumulative density function for the skew normal
72  * distribution.
73  *
74  * @param h var parameter.
75  * @param a double parameter.
76  * @return The Owen's T function.
77  */
owens_t(const var & h,double a)78 inline var owens_t(const var& h, double a) {
79   return var(new internal::owens_t_vd_vari(h.vi_, a));
80 }
81 
82 /**
83  * The Owen's T function of h and a.
84  *
85  * Used to compute the cumulative density function for the skew normal
86  * distribution.
87  *
88  * @param h double parameter.
89  * @param a var parameter.
90  * @return The Owen's T function.
91  */
owens_t(double h,const var & a)92 inline var owens_t(double h, const var& a) {
93   return var(new internal::owens_t_dv_vari(h, a.vi_));
94 }
95 
96 }  // namespace math
97 }  // namespace stan
98 #endif
99