Stan Math Library  2.20.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 
4 #include <stan/math/rev/meta.hpp>
10 #include <stan/math/rev/core.hpp>
12 #include <cmath>
13 
14 namespace stan {
15 namespace math {
16 
17 namespace internal {
18 class unit_vector_elt_vari : public vari {
19  private:
20  vari** y_;
21  const double* unit_vector_y_;
22  const int size_;
23  const int idx_;
24  const double norm_;
25 
26  public:
27  unit_vector_elt_vari(double val, vari** y, const double* unit_vector_y,
28  int size, int idx, double norm)
29  : vari(val),
30  y_(y),
31  unit_vector_y_(unit_vector_y),
32  size_(size),
33  idx_(idx),
34  norm_(norm) {}
35  void chain() {
36  const double cubed_norm = norm_ * norm_ * norm_;
37  for (int m = 0; m < size_; ++m) {
38  y_[m]->adj_
39  -= adj_ * unit_vector_y_[m] * unit_vector_y_[idx_] / cubed_norm;
40  if (m == idx_)
41  y_[m]->adj_ += adj_ / norm_;
42  }
43  }
44 };
45 } // namespace internal
46 
55 template <int R, int C>
56 Eigen::Matrix<var, R, C> unit_vector_constrain(
57  const Eigen::Matrix<var, R, C>& y) {
58  check_vector("unit_vector", "y", y);
59  check_nonzero_size("unit_vector", "y", y);
60 
61  vari** y_vi_array = reinterpret_cast<vari**>(
62  ChainableStack::instance_->memalloc_.alloc(sizeof(vari*) * y.size()));
63  for (int i = 0; i < y.size(); ++i)
64  y_vi_array[i] = y.coeff(i).vi_;
65 
66  Eigen::VectorXd y_d(y.size());
67  for (int i = 0; i < y.size(); ++i)
68  y_d.coeffRef(i) = y.coeff(i).val();
69 
70  const double norm = y_d.norm();
71  check_positive_finite("unit_vector", "norm", norm);
72  Eigen::VectorXd unit_vector_d = y_d / norm;
73 
74  double* unit_vector_y_d_array = reinterpret_cast<double*>(
75  ChainableStack::instance_->memalloc_.alloc(sizeof(double) * y_d.size()));
76  for (int i = 0; i < y_d.size(); ++i)
77  unit_vector_y_d_array[i] = unit_vector_d.coeff(i);
78 
79  Eigen::Matrix<var, R, C> unit_vector_y(y.size());
80  for (int k = 0; k < y.size(); ++k)
81  unit_vector_y.coeffRef(k) = var(new internal::unit_vector_elt_vari(
82  unit_vector_d[k], y_vi_array, unit_vector_y_d_array, y.size(), k,
83  norm));
84  return unit_vector_y;
85 }
86 
96 template <int R, int C>
97 Eigen::Matrix<var, R, C> unit_vector_constrain(
98  const Eigen::Matrix<var, R, C>& y, var& lp) {
99  Eigen::Matrix<var, R, C> x = unit_vector_constrain(y);
100  lp -= 0.5 * dot_self(y);
101  return x;
102 }
103 
104 } // namespace math
105 } // namespace stan
106 #endif
unit_vector_elt_vari(double val, vari **y, const double *unit_vector_y, int size, int idx, double norm)
void check_nonzero_size(const char *function, const char *name, const T_y &y)
Check if the specified matrix/vector is of non-zero size.
The variable implementation base class.
Definition: vari.hpp:30
void check_vector(const char *function, const char *name, const Eigen::Matrix< T, R, C > &x)
Check if the matrix is either a row vector or column vector.
static STAN_THREADS_DEF AutodiffStackStorage * instance_
Independent (input) and dependent (output) variables for gradients.
Definition: var.hpp:33
fvar< T > dot_self(const Eigen::Matrix< fvar< T >, R, C > &v)
Definition: dot_self.hpp:13
friend class var
Definition: vari.hpp:32
Eigen::Matrix< fvar< T >, R, C > unit_vector_constrain(const Eigen::Matrix< fvar< T >, R, C > &y)
void check_positive_finite(const char *function, const char *name, const T_y &y)
Check if y is positive and finite.
int size(const std::vector< T > &x)
Return the size of the specified standard vector.
Definition: size.hpp:17
void chain()
Apply the chain rule to this variable based on the variables on which it depends. ...
double adj_
The adjoint of this variable, which is the partial derivative of this variable with respect to the ro...
Definition: vari.hpp:44
void * alloc(size_t len)
Return a newly allocated block of memory of the appropriate size managed by the stack allocator...

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