Stan Math Library  2.14.0
reverse mode automatic differentiation
dot_product.hpp
Go to the documentation of this file.
1 #ifndef STAN_MATH_REV_MAT_FUN_DOT_PRODUCT_HPP
2 #define STAN_MATH_REV_MAT_FUN_DOT_PRODUCT_HPP
3 
9 #include <stan/math/rev/core.hpp>
12 #include <boost/utility/enable_if.hpp>
13 #include <boost/type_traits.hpp>
14 #include <vector>
15 
16 namespace stan {
17  namespace math {
18 
19  namespace {
20  template<typename T>
21  struct dot_product_store_type;
22 
23  template<>
24  struct dot_product_store_type<var> {
25  typedef vari** type;
26  };
27 
28  template<>
29  struct dot_product_store_type<double> {
30  typedef double* type;
31  };
32 
33  template<typename T1, typename T2>
34  class dot_product_vari : public vari {
35  protected:
36  typename dot_product_store_type<T1>::type v1_;
37  typename dot_product_store_type<T2>::type v2_;
38  size_t length_;
39 
40  inline static double var_dot(vari** v1, vari** v2,
41  size_t length) {
42  Eigen::VectorXd vd1(length), vd2(length);
43  for (size_t i = 0; i < length; i++) {
44  vd1[i] = v1[i]->val_;
45  vd2[i] = v2[i]->val_;
46  }
47  return vd1.dot(vd2);
48  }
49 
50  inline static double var_dot(const T1* v1, const T2* v2,
51  size_t length) {
52  Eigen::VectorXd vd1(length), vd2(length);
53  for (size_t i = 0; i < length; i++) {
54  vd1[i] = value_of(v1[i]);
55  vd2[i] = value_of(v2[i]);
56  }
57  return vd1.dot(vd2);
58  }
59 
60  template<typename Derived1, typename Derived2>
61  inline static double var_dot(const Eigen::DenseBase<Derived1> &v1,
62  const Eigen::DenseBase<Derived2> &v2) {
63  Eigen::VectorXd vd1(v1.size()), vd2(v1.size());
64  for (int i = 0; i < v1.size(); i++) {
65  vd1[i] = value_of(v1[i]);
66  vd2[i] = value_of(v2[i]);
67  }
68  return vd1.dot(vd2);
69  }
70  inline void chain(vari** v1, vari** v2) {
71  for (size_t i = 0; i < length_; i++) {
72  v1[i]->adj_ += adj_ * v2_[i]->val_;
73  v2[i]->adj_ += adj_ * v1_[i]->val_;
74  }
75  }
76  inline void chain(double* v1, vari** v2) {
77  for (size_t i = 0; i < length_; i++) {
78  v2[i]->adj_ += adj_ * v1_[i];
79  }
80  }
81  inline void chain(vari** v1, double* v2) {
82  for (size_t i = 0; i < length_; i++) {
83  v1[i]->adj_ += adj_ * v2_[i];
84  }
85  }
86  inline void initialize(vari** &mem_v, const var *inv,
87  vari **shared = NULL) {
88  if (shared == NULL) {
89  mem_v = reinterpret_cast<vari**>(ChainableStack::memalloc_
90  .alloc(length_*sizeof(vari*)));
91  for (size_t i = 0; i < length_; i++)
92  mem_v[i] = inv[i].vi_;
93  } else {
94  mem_v = shared;
95  }
96  }
97  template<typename Derived>
98  inline void initialize(vari** &mem_v,
99  const Eigen::DenseBase<Derived> &inv,
100  vari **shared = NULL) {
101  if (shared == NULL) {
102  mem_v = reinterpret_cast<vari**>(ChainableStack::memalloc_
103  .alloc(length_*sizeof(vari*)));
104  for (size_t i = 0; i < length_; i++)
105  mem_v[i] = inv(i).vi_;
106  } else {
107  mem_v = shared;
108  }
109  }
110 
111  inline void initialize(double* &mem_d, const double *ind,
112  double *shared = NULL) {
113  if (shared == NULL) {
114  mem_d = reinterpret_cast<double*>(ChainableStack::memalloc_
115  .alloc(length_*sizeof(double)));
116  for (size_t i = 0; i < length_; i++)
117  mem_d[i] = ind[i];
118  } else {
119  mem_d = shared;
120  }
121  }
122  template<typename Derived>
123  inline void initialize(double* &mem_d,
124  const Eigen::DenseBase<Derived> &ind,
125  double *shared = NULL) {
126  if (shared == NULL) {
127  mem_d = reinterpret_cast<double*>
128  (ChainableStack::memalloc_.alloc(length_*sizeof(double)));
129  for (size_t i = 0; i < length_; i++)
130  mem_d[i] = ind(i);
131  } else {
132  mem_d = shared;
133  }
134  }
135 
136  public:
137  dot_product_vari(typename dot_product_store_type<T1>::type v1,
138  typename dot_product_store_type<T2>::type v2,
139  size_t length)
140  : vari(var_dot(v1, v2, length)), v1_(v1), v2_(v2), length_(length) {}
141 
142  dot_product_vari(const T1* v1, const T2* v2, size_t length,
143  dot_product_vari<T1, T2>* shared_v1 = NULL,
144  dot_product_vari<T1, T2>* shared_v2 = NULL) :
145  vari(var_dot(v1, v2, length)), length_(length) {
146  if (shared_v1 == NULL) {
147  initialize(v1_, v1);
148  } else {
149  initialize(v1_, v1, shared_v1->v1_);
150  }
151  if (shared_v2 == NULL) {
152  initialize(v2_, v2);
153  } else {
154  initialize(v2_, v2, shared_v2->v2_);
155  }
156  }
157  template<typename Derived1, typename Derived2>
158  dot_product_vari(const Eigen::DenseBase<Derived1> &v1,
159  const Eigen::DenseBase<Derived2> &v2,
160  dot_product_vari<T1, T2>* shared_v1 = NULL,
161  dot_product_vari<T1, T2>* shared_v2 = NULL) :
162  vari(var_dot(v1, v2)), length_(v1.size()) {
163  if (shared_v1 == NULL) {
164  initialize(v1_, v1);
165  } else {
166  initialize(v1_, v1, shared_v1->v1_);
167  }
168  if (shared_v2 == NULL) {
169  initialize(v2_, v2);
170  } else {
171  initialize(v2_, v2, shared_v2->v2_);
172  }
173  }
174  template<int R1, int C1, int R2, int C2>
175  dot_product_vari(const Eigen::Matrix<T1, R1, C1> &v1,
176  const Eigen::Matrix<T2, R2, C2> &v2,
177  dot_product_vari<T1, T2>* shared_v1 = NULL,
178  dot_product_vari<T1, T2>* shared_v2 = NULL) :
179  vari(var_dot(v1, v2)), length_(v1.size()) {
180  if (shared_v1 == NULL) {
181  initialize(v1_, v1);
182  } else {
183  initialize(v1_, v1, shared_v1->v1_);
184  }
185  if (shared_v2 == NULL) {
186  initialize(v2_, v2);
187  } else {
188  initialize(v2_, v2, shared_v2->v2_);
189  }
190  }
191  virtual void chain() {
192  chain(v1_, v2_);
193  }
194  };
195  }
196 
205  template<typename T1, int R1, int C1, typename T2, int R2, int C2>
206  inline
207  typename boost::enable_if_c<boost::is_same<T1, var>::value ||
208  boost::is_same<T2, var>::value, var>::type
209  dot_product(const Eigen::Matrix<T1, R1, C1>& v1,
210  const Eigen::Matrix<T2, R2, C2>& v2) {
211  check_vector("dot_product", "v1", v1);
212  check_vector("dot_product", "v2", v2);
213  check_matching_sizes("dot_product",
214  "v1", v1,
215  "v2", v2);
216  return var(new dot_product_vari<T1, T2>(v1, v2));
217  }
226  template<typename T1, typename T2>
227  inline
228  typename boost::enable_if_c<boost::is_same<T1, var>::value ||
229  boost::is_same<T2, var>::value, var>::type
230  dot_product(const T1* v1, const T2* v2, size_t length) {
231  return var(new dot_product_vari<T1, T2>(v1, v2, length));
232  }
233 
242  template<typename T1, typename T2>
243  inline
244  typename boost::enable_if_c<boost::is_same<T1, var>::value ||
245  boost::is_same<T2, var>::value, var>::type
246  dot_product(const std::vector<T1>& v1,
247  const std::vector<T2>& v2) {
248  check_matching_sizes("dot_product",
249  "v1", v1,
250  "v2", v2);
251  return var(new dot_product_vari<T1, T2>(&v1[0], &v2[0], v1.size()));
252  }
253 
254  }
255 }
256 #endif
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
dot_product_store_type< T1 >::type v1_
Definition: dot_product.hpp:36
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.
size_t length(const std::vector< T > &x)
Definition: length.hpp:10
Independent (input) and dependent (output) variables for gradients.
Definition: var.hpp:30
dot_product_store_type< T2 >::type v2_
Definition: dot_product.hpp:37
void initialize(T &x, const T &v)
Definition: initialize.hpp:16
fvar< T > dot_product(const Eigen::Matrix< fvar< T >, R1, C1 > &v1, const Eigen::Matrix< fvar< T >, R2, C2 > &v2)
Definition: dot_product.hpp:18
void check_matching_sizes(const char *function, const char *name1, const T_y1 &y1, const char *name2, const T_y2 &y2)
Check if two structures at the same size.
size_t length_
Definition: dot_product.hpp:38
void * alloc(size_t len)
Return a newly allocated block of memory of the appropriate size managed by the stack allocator...
fvar< T > inv(const fvar< T > &x)
Definition: inv.hpp:14

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