Stan Math Library  2.11.0
reverse mode automatic differentiation
unit_vector_constrain.hpp
Go to the documentation of this file.
1 #ifndef STAN_MATH_PRIM_MAT_FUN_UNIT_VECTOR_CONSTRAIN_HPP
2 #define STAN_MATH_PRIM_MAT_FUN_UNIT_VECTOR_CONSTRAIN_HPP
3 
9 #include <stan/math/rev/core.hpp>
11 #include <cmath>
12 
13 namespace stan {
14  namespace math {
15 
16  namespace {
17  class unit_vector_elt_vari : public vari {
18  private:
19  vari** y_;
20  const double* unit_vector_y_;
21  const int size_;
22  const int idx_;
23  const double norm_;
24 
25  public:
26  unit_vector_elt_vari(double val,
27  vari** y,
28  const double* unit_vector_y,
29  int size,
30  int idx,
31  const double norm)
32  : vari(val),
33  y_(y),
34  unit_vector_y_(unit_vector_y),
35  size_(size),
36  idx_(idx),
37  norm_(norm) {
38  }
39  void chain() {
40  const double cubed_norm = norm_ * norm_ * norm_;
41  for (int m = 0; m < size_; ++m) {
42  y_[m]->adj_
43  -= adj_ * unit_vector_y_[m] * unit_vector_y_[idx_] / cubed_norm;
44  if (m == idx_)
45  y_[m]->adj_ += adj_ / norm_;
46  }
47  }
48  };
49  }
50 
51 
52  // Unit vector
53 
62  template <int R, int C>
63  Eigen::Matrix<var, R, C>
64  unit_vector_constrain(const Eigen::Matrix<var, R, C>& y) {
65  stan::math::check_vector("unit_vector", "y", y);
66  stan::math::check_nonzero_size("unit_vector", "y", y);
67 
68  vari** y_vi_array
69  = reinterpret_cast<vari**>(ChainableStack::memalloc_
70  .alloc(sizeof(vari*) * y.size()));
71  for (int i = 0; i < y.size(); ++i)
72  y_vi_array[i] = y.coeff(i).vi_;
73 
74  Eigen::VectorXd y_d(y.size());
75  for (int i = 0; i < y.size(); ++i)
76  y_d.coeffRef(i) = y.coeff(i).val();
77 
78 
79  const double norm = y_d.norm();
80  stan::math::check_positive_finite("unit_vector", "norm", norm);
81  Eigen::VectorXd unit_vector_d = y_d / norm;
82 
83  double* unit_vector_y_d_array
84  = reinterpret_cast<double*>(ChainableStack::memalloc_
85  .alloc(sizeof(double) * y_d.size()));
86  for (int i = 0; i < y_d.size(); ++i)
87  unit_vector_y_d_array[i] = unit_vector_d.coeff(i);
88 
89  Eigen::Matrix<var, R, C> unit_vector_y(y.size());
90  for (int k = 0; k < y.size(); ++k)
91  unit_vector_y.coeffRef(k)
92  = var(new unit_vector_elt_vari(unit_vector_d[k],
93  y_vi_array,
94  unit_vector_y_d_array,
95  y.size(),
96  k,
97  norm));
98  return unit_vector_y;
99  }
100 
110  template <int R, int C>
111  Eigen::Matrix<var, R, C>
112  unit_vector_constrain(const Eigen::Matrix<var, R, C>& y, var &lp) {
113  Eigen::Matrix<var, R, C> x = unit_vector_constrain(y);
114  lp -= 0.5 * stan::math::dot_self(y);
115  return x;
116  }
117 
118  }
119 
120 }
121 
122 #endif
bool check_vector(const char *function, const char *name, const Eigen::Matrix< T, R, C > &x)
Return true if the matrix is either a row vector or column vector.
vari ** y_
The variable implementation base class.
Definition: vari.hpp:30
const double * unit_vector_y_
Independent (input) and dependent (output) variables for gradients.
Definition: var.hpp:31
fvar< T > dot_self(const Eigen::Matrix< fvar< T >, R, C > &v)
Definition: dot_self.hpp:16
bool check_nonzero_size(const char *function, const char *name, const T_y &y)
Return true if the specified matrix/vector is of non-zero size.
Eigen::Matrix< fvar< T >, R, C > unit_vector_constrain(const Eigen::Matrix< fvar< T >, R, C > &y)
int size(const std::vector< T > &x)
Return the size of the specified standard vector.
Definition: size.hpp:17
const double norm_
const int size_
bool check_positive_finite(const char *function, const char *name, const T_y &y)
Return true if y is positive and finite.
void * alloc(size_t len)
Return a newly allocated block of memory of the appropriate size managed by the stack allocator...
const int idx_

     [ Stan Home Page ] © 2011–2016, Stan Development Team.