1 #ifndef STAN_MATH_REV_MAT_FUNCTOR_ADJ_JAC_APPLY_HPP
2 #define STAN_MATH_REV_MAT_FUNCTOR_ADJ_JAC_APPLY_HPP
3 
4 #include <stan/math/prim/scal/meta/scalar_type.hpp>
5 #include <stan/math/prim/mat/fun/Eigen.hpp>
6 #include <stan/math/prim/mat/fun/value_of.hpp>
7 #include <stan/math/rev/scal/fun/value_of.hpp>
8 #include <stan/math/rev/scal/meta/is_var.hpp>
9 #include <limits>
10 #include <tuple>
11 #include <vector>
12 
13 namespace stan {
14 namespace math {
15 
16 namespace internal {
17 /**
18  * Invoke the functor f with arguments given in t and indexed in the index
19  * sequence I
20  *
21  * @tparam F Type of functor
22  * @tparam Tuple Type of tuple containing arguments
23  * @tparam I Index sequence going from 0 to std::tuple_size<T>::value - 1
24  * inclusive
25  * @param f functor callable
26  * @param t tuple of arguments
27  * @param i placeholder variable for index sequence
28  */
29 template <class F, class Tuple, std::size_t... I>
apply_impl(const F & f,const Tuple & t,std::index_sequence<I...> i)30 constexpr auto apply_impl(const F& f, const Tuple& t,
31                           std::index_sequence<I...> i) {
32   return f(std::get<I>(t)...);
33 }
34 
35 /**
36  * Call the functor f with the tuple of arguments t, like:
37  *
38  * f(std::get<0>(t), std::get<1>(t), ...)
39  *
40  * TODO: replace this with implementation in C++ std when C++17 is available
41  *
42  * @tparam F Type of functor
43  * @tparam Tuple Type of tuple containing arguments
44  * @param f functor callable
45  * @param t tuple of arguments
46  */
47 template <class F, class Tuple>
apply(const F & f,const Tuple & t)48 constexpr auto apply(const F& f, const Tuple& t) {
49   return apply_impl(f, t, std::make_index_sequence<std::tuple_size<Tuple>{}>{});
50 }
51 
52 /**
53  * Store the adjoint in y_vi[0] in y_adj
54  *
55  * @tparam size dimensionality of M
56  * @param[in] y_vi pointer to pointer to vari
57  * @param[in] M
58  * @param[out] y_adj reference to variable where adjoint is to be stored
59  */
60 template <size_t size>
build_y_adj(vari ** y_vi,const std::array<int,size> & M,double & y_adj)61 void build_y_adj(vari** y_vi, const std::array<int, size>& M, double& y_adj) {
62   y_adj = y_vi[0]->adj_;
63 }
64 
65 /**
66  * Store the adjoints from y_vi in y_adj
67  *
68  * @tparam size dimensionality of M
69  * @param[in] y_vi pointer to pointers to varis
70  * @param[in] M shape of y_adj
71  * @param[out] y_adj reference to std::vector where adjoints are to be stored
72  */
73 template <size_t size>
build_y_adj(vari ** y_vi,const std::array<int,size> & M,std::vector<double> & y_adj)74 void build_y_adj(vari** y_vi, const std::array<int, size>& M,
75                  std::vector<double>& y_adj) {
76   y_adj.resize(M[0]);
77   for (size_t m = 0; m < y_adj.size(); ++m)
78     y_adj[m] = y_vi[m]->adj_;
79 }
80 
81 /**
82  * Store the adjoints from y_vi in y_adj
83  *
84  * @tparam size dimensionality of M
85  * @param[in] y_vi pointer to pointers to varis
86  * @param[in] M shape of y_adj
87  * @param[out] y_adj reference to Eigen::Matrix where adjoints are to be stored
88  */
89 template <size_t size, int R, int C>
build_y_adj(vari ** y_vi,const std::array<int,size> & M,Eigen::Matrix<double,R,C> & y_adj)90 void build_y_adj(vari** y_vi, const std::array<int, size>& M,
91                  Eigen::Matrix<double, R, C>& y_adj) {
92   y_adj.resize(M[0], M[1]);
93   for (int m = 0; m < y_adj.size(); ++m)
94     y_adj(m) = y_vi[m]->adj_;
95 }
96 
97 /**
98  * Compute the dimensionality of the given template argument. The
99  * definition of dimensionality is deferred to specializations. By
100  * default don't have a value (fail to compile)
101  */
102 template <typename T>
103 struct compute_dims {};
104 
105 /**
106  * Compute the dimensionality of the given template argument. Double
107  * types hav dimensionality zero.
108  */
109 template <>
110 struct compute_dims<double> {
111   static constexpr size_t value = 0;
112 };
113 
114 /**
115  * Compute the dimensionality of the given template argument.
116  * std::vector has dimension 1
117  */
118 template <typename T>
119 struct compute_dims<std::vector<T>> {
120   static constexpr size_t value = 1;
121 };
122 
123 /**
124  * compute the dimensionality of the given template argument.
125  * Eigen::Matrix types all have dimension two
126  */
127 template <typename T, int R, int C>
128 struct compute_dims<Eigen::Matrix<T, R, C>> {
129   static constexpr size_t value = 2;
130 };
131 }  // namespace internal
132 
133 /**
134  * adj_jac_vari interfaces a user supplied functor  with the reverse mode
135  * autodiff. It allows someone to implement functions with custom reverse mode
136  * autodiff without having to deal with autodiff types.
137  *
138  * The requirements on the functor F are described in the documentation for
139  * adj_jac_apply
140  *
141  * Targs (the input argument types) can be any mix of double, var, or
142  * Eigen::Matrices with double or var scalar components
143  *
144  * @tparam F class of functor
145  * @tparam Targs Types of arguments
146  */
147 template <typename F, typename... Targs>
148 struct adj_jac_vari : public vari {
149   std::array<bool, sizeof...(Targs)> is_var_;
150   using FReturnType
151       = std::result_of_t<F(decltype(is_var_), decltype(value_of(Targs()))...)>;
152 
153   F f_;
154   std::array<int, sizeof...(Targs)> offsets_;
155   vari** x_vis_;
156   std::array<int, internal::compute_dims<FReturnType>::value> M_;
157   vari** y_vi_;
158 
159   /**
160    * count_memory returns count (the first argument) + the number of varis used
161    * in the second argument + the number of arguments used to encode the
162    * variadic tail args.
163    *
164    * The adj_jac_vari constructor uses this to figure out how much space to
165    * allocate in x_vis_.
166    *
167    * The array offsets_ is populated with values to indicate where in x_vis_ the
168    * vari pointers for each argument will be stored.
169    *
170    * Each of the arguments can be an Eigen::Matrix with var or double scalar
171    * types, a std::vector with var, double, or int scalar types, or a var, a
172    * double, or an int.
173    *
174    * @tparam R Eigen Matrix row type
175    * @tparam C Eigen Matrix column type
176    * @tparam Pargs Types of rest of arguments
177    * @param count rolling count of number of varis that must be allocated
178    * @param x next argument to have its varis counted
179    * @param args the rest of the arguments (that will be iterated through
180    * recursively)
181    */
182   template <int R, int C, typename... Pargs>
count_memorystan::math::adj_jac_vari183   size_t count_memory(size_t count, const Eigen::Matrix<var, R, C>& x,
184                       const Pargs&... args) {
185     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
186     offsets_[t] = count;
187     count += x.size();
188     return count_memory(count, args...);
189   }
190 
191   template <int R, int C, typename... Pargs>
count_memorystan::math::adj_jac_vari192   size_t count_memory(size_t count, const Eigen::Matrix<double, R, C>& x,
193                       const Pargs&... args) {
194     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
195     offsets_[t] = count;
196     return count_memory(count, args...);
197   }
198 
199   template <typename... Pargs>
count_memorystan::math::adj_jac_vari200   size_t count_memory(size_t count, const std::vector<var>& x,
201                       const Pargs&... args) {
202     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
203     offsets_[t] = count;
204     count += x.size();
205     return count_memory(count, args...);
206   }
207 
208   template <typename... Pargs>
count_memorystan::math::adj_jac_vari209   size_t count_memory(size_t count, const std::vector<double>& x,
210                       const Pargs&... args) {
211     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
212     offsets_[t] = count;
213     return count_memory(count, args...);
214   }
215 
216   template <typename... Pargs>
count_memorystan::math::adj_jac_vari217   size_t count_memory(size_t count, const std::vector<int>& x,
218                       const Pargs&... args) {
219     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
220     offsets_[t] = count;
221     return count_memory(count, args...);
222   }
223 
224   template <typename... Pargs>
count_memorystan::math::adj_jac_vari225   size_t count_memory(size_t count, const var& x, const Pargs&... args) {
226     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
227     offsets_[t] = count;
228     count += 1;
229     return count_memory(count, args...);
230   }
231 
232   template <typename... Pargs>
count_memorystan::math::adj_jac_vari233   size_t count_memory(size_t count, const double& x, const Pargs&... args) {
234     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
235     offsets_[t] = count;
236     return count_memory(count, args...);
237   }
238 
239   template <typename... Pargs>
count_memorystan::math::adj_jac_vari240   size_t count_memory(size_t count, const int& x, const Pargs&... args) {
241     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
242     offsets_[t] = count;
243     return count_memory(count, args...);
244   }
245 
count_memorystan::math::adj_jac_vari246   size_t count_memory(size_t count) { return count; }
247 
248   /**
249    * prepare_x_vis populates x_vis_ with the varis from each of its
250    * input arguments. The vari pointers for argument n are copied into x_vis_ at
251    * the index starting at offsets_[n]. For Eigen::Matrix types, this copying is
252    * done in with column major ordering.
253    *
254    * Each of the arguments can be an Eigen::Matrix with var or double scalar
255    * types, a std::vector with var, double, or int scalar types, or a var, a
256    * double, or an int.
257    *
258    * @tparam R Eigen Matrix row type
259    * @tparam C Eigen Matrix column type
260    * @tparam Pargs Types of the rest of the arguments to be processed
261    * @param x next argument to have its vari pointers copied if necessary
262    * @param args the rest of the arguments (that will be iterated through
263    * recursively)
264    */
265   template <int R, int C, typename... Pargs>
prepare_x_visstan::math::adj_jac_vari266   void prepare_x_vis(const Eigen::Matrix<var, R, C>& x, const Pargs&... args) {
267     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
268     for (int i = 0; i < x.size(); ++i) {
269       x_vis_[offsets_[t] + i] = x(i).vi_;
270     }
271     prepare_x_vis(args...);
272   }
273 
274   template <int R, int C, typename... Pargs>
prepare_x_visstan::math::adj_jac_vari275   void prepare_x_vis(const Eigen::Matrix<double, R, C>& x,
276                      const Pargs&... args) {
277     prepare_x_vis(args...);
278   }
279 
280   template <typename... Pargs>
prepare_x_visstan::math::adj_jac_vari281   void prepare_x_vis(const std::vector<var>& x, const Pargs&... args) {
282     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
283     for (size_t i = 0; i < x.size(); ++i) {
284       x_vis_[offsets_[t] + i] = x[i].vi_;
285     }
286     prepare_x_vis(args...);
287   }
288 
289   template <typename... Pargs>
prepare_x_visstan::math::adj_jac_vari290   void prepare_x_vis(const std::vector<double>& x, const Pargs&... args) {
291     prepare_x_vis(args...);
292   }
293 
294   template <typename... Pargs>
prepare_x_visstan::math::adj_jac_vari295   void prepare_x_vis(const std::vector<int>& x, const Pargs&... args) {
296     prepare_x_vis(args...);
297   }
298 
299   template <typename... Pargs>
prepare_x_visstan::math::adj_jac_vari300   void prepare_x_vis(const var& x, const Pargs&... args) {
301     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
302     x_vis_[offsets_[t]] = x.vi_;
303     prepare_x_vis(args...);
304   }
305 
306   template <typename... Pargs>
prepare_x_visstan::math::adj_jac_vari307   void prepare_x_vis(const double& x, const Pargs&... args) {
308     prepare_x_vis(args...);
309   }
310 
311   template <typename... Pargs>
prepare_x_visstan::math::adj_jac_vari312   void prepare_x_vis(const int& x, const Pargs&... args) {
313     prepare_x_vis(args...);
314   }
315 
316   /**
317    * Initializes is_var_ with true if the scalar type in each argument
318    * is a var (and false if not)
319    */
adj_jac_varistan::math::adj_jac_vari320   adj_jac_vari()
321       : vari(std::numeric_limits<double>::quiet_NaN()),  // The val_ in this
322                                                          // vari is unused
323         is_var_({{is_var<typename scalar_type<Targs>::type>::value...}}),
324         x_vis_(NULL),
325         y_vi_(NULL) {}
326 
327   /**
328    * Return a var with a new vari holding the given value
329    *
330    * @param val_y output of F::operator()
331    * @return var
332    */
build_return_varis_and_varsstan::math::adj_jac_vari333   var build_return_varis_and_vars(const double& val_y) {
334     y_vi_ = ChainableStack::instance().memalloc_.alloc_array<vari*>(1);
335     y_vi_[0] = new vari(val_y, false);
336 
337     return y_vi_[0];
338   }
339 
340   /**
341    * Return a std::vector of vars created from newly allocated varis initialized
342    * with the values of val_y
343    *
344    * @param val_y output of F::operator()
345    * @return std::vector of vars
346    */
build_return_varis_and_varsstan::math::adj_jac_vari347   std::vector<var> build_return_varis_and_vars(
348       const std::vector<double>& val_y) {
349     M_[0] = val_y.size();
350     std::vector<var> var_y(M_[0]);
351 
352     y_vi_
353         = ChainableStack::instance().memalloc_.alloc_array<vari*>(var_y.size());
354     for (size_t m = 0; m < var_y.size(); ++m) {
355       y_vi_[m] = new vari(val_y[m], false);
356       var_y[m] = y_vi_[m];
357     }
358 
359     return var_y;
360   }
361 
362   /**
363    * Return an Eigen::Matrix of vars created from newly allocated varis
364    * initialized with the values of val_y. The shape of the new matrix comes
365    * from M_
366    *
367    * @tparam R Eigen row type
368    * @tparam C Eigen column type
369    * @param val_y output of F::operator()
370    * @return Eigen::Matrix of vars
371    */
372   template <int R, int C>
build_return_varis_and_varsstan::math::adj_jac_vari373   Eigen::Matrix<var, R, C> build_return_varis_and_vars(
374       const Eigen::Matrix<double, R, C>& val_y) {
375     M_[0] = val_y.rows();
376     M_[1] = val_y.cols();
377     Eigen::Matrix<var, R, C> var_y(M_[0], M_[1]);
378 
379     y_vi_
380         = ChainableStack::instance().memalloc_.alloc_array<vari*>(var_y.size());
381     for (int m = 0; m < var_y.size(); ++m) {
382       y_vi_[m] = new vari(val_y(m), false);
383       var_y(m) = y_vi_[m];
384     }
385 
386     return var_y;
387   }
388 
prepare_x_visstan::math::adj_jac_vari389   void prepare_x_vis() {}
390 
391   /**
392    * The adj_jac_vari functor
393    *  1. Initializes an instance of the user defined functor F
394    *  2. Calls operator() on the F instance with the double values from the
395    * input args
396    *  3. Saves copies of the varis pointed to by the input vars for subsequent
397    * calls to chain
398    *  4. Calls build_return_varis_and_vars to construct the appropriate output
399    * data structure of vars
400    *
401    * Each of the arguments can be an Eigen::Matrix with var or double scalar
402    * types, a std::vector with var, double, or int scalar types, or a var, a
403    * double, or an int.
404    *
405    * @param args Input arguments
406    * @return Output of f_ as vars
407    */
operator ()stan::math::adj_jac_vari408   auto operator()(const Targs&... args) {
409     x_vis_ = ChainableStack::instance().memalloc_.alloc_array<vari*>(
410         count_memory(0, args...));
411 
412     prepare_x_vis(args...);
413 
414     return build_return_varis_and_vars(f_(is_var_, value_of(args)...));
415   }
416 
417   /**
418    * Accumulate, if necessary, the values of y_adj_jac into the
419    * adjoints of the varis pointed to by the appropriate elements
420    * of x_vis_. Recursively calls accumulate_adjoints on the rest of the
421    * arguments.
422    *
423    * @tparam R Eigen Matrix row type
424    * @tparam C Eigen Matrix column type
425    * @tparam Pargs Types of the rest of adjoints to accumulate
426    * @param y_adj_jac set of values to be accumulated in adjoints
427    * @param args the rest of the arguments (that will be iterated through
428    * recursively)
429    */
430   template <int R, int C, typename... Pargs>
accumulate_adjointsstan::math::adj_jac_vari431   void accumulate_adjoints(const Eigen::Matrix<double, R, C>& y_adj_jac,
432                            const Pargs&... args) {
433     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
434     if (is_var_[t]) {
435       for (int n = 0; n < y_adj_jac.size(); ++n) {
436         x_vis_[offsets_[t] + n]->adj_ += y_adj_jac(n);
437       }
438     }
439 
440     accumulate_adjoints(args...);
441   }
442 
443   /**
444    * Accumulate, if necessary, the values of y_adj_jac into the
445    * adjoints of the varis pointed to by the appropriate elements
446    * of x_vis_. Recursively calls accumulate_adjoints on the rest of the
447    * arguments.
448    *
449    * @tparam Pargs Types of the rest of adjoints to accumulate
450    * @param y_adj_jac set of values to be accumulated in adjoints
451    * @param args the rest of the arguments (that will be iterated through
452    * recursively)
453    */
454   template <typename... Pargs>
accumulate_adjointsstan::math::adj_jac_vari455   void accumulate_adjoints(const std::vector<double>& y_adj_jac,
456                            const Pargs&... args) {
457     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
458     if (is_var_[t]) {
459       for (size_t n = 0; n < y_adj_jac.size(); ++n)
460         x_vis_[offsets_[t] + n]->adj_ += y_adj_jac[n];
461     }
462 
463     accumulate_adjoints(args...);
464   }
465 
466   /**
467    * Recursively call accumulate_adjoints with args. There are no adjoints to
468    * accumulate for std::vector<int> arguments.
469    *
470    * @tparam Pargs Types of the rest of adjoints to accumulate
471    * @param y_adj_jac ignored
472    * @param args the rest of the arguments (that will be iterated through
473    * recursively)
474    */
475   template <typename... Pargs>
accumulate_adjointsstan::math::adj_jac_vari476   void accumulate_adjoints(const std::vector<int>& y_adj_jac,
477                            const Pargs&... args) {
478     accumulate_adjoints(args...);
479   }
480 
481   /**
482    * Accumulate, if necessary, the value of y_adj_jac into the
483    * adjoint of the vari pointed to by the appropriate element
484    * of x_vis_. Recursively calls accumulate_adjoints on the rest of the
485    * arguments.
486    *
487    * @tparam Pargs Types of the rest of adjoints to accumulate
488    * @param y_adj_jac next set of adjoints to be accumulated
489    * @param args the rest of the arguments (that will be iterated through
490    * recursively)
491    */
492   template <typename... Pargs>
accumulate_adjointsstan::math::adj_jac_vari493   void accumulate_adjoints(const double& y_adj_jac, const Pargs&... args) {
494     static constexpr int t = sizeof...(Targs) - sizeof...(Pargs) - 1;
495     if (is_var_[t]) {
496       x_vis_[offsets_[t]]->adj_ += y_adj_jac;
497     }
498 
499     accumulate_adjoints(args...);
500   }
501 
502   /**
503    * Recursively call accumulate_adjoints with args. There are no adjoints to
504    * accumulate for int arguments.
505    *
506    * @tparam Pargs Types of the rest of adjoints to accumulate
507    * @param y_adj_jac ignored
508    * @param args the rest of the arguments (that will be iterated through
509    * recursively)
510    */
511   template <typename... Pargs>
accumulate_adjointsstan::math::adj_jac_vari512   void accumulate_adjoints(const int& y_adj_jac, const Pargs&... args) {
513     accumulate_adjoints(args...);
514   }
515 
accumulate_adjointsstan::math::adj_jac_vari516   void accumulate_adjoints() {}
517 
518   /**
519    * Propagate the adjoints at the output varis (y_vi_) back to the input
520    * varis (x_vis_) by:
521    * 1. packing the adjoints in an appropriate container using build_y_adj
522    * 2. using the multiply_adjoint_jacobian function of the user defined functor
523    * to compute what the adjoints on x_vis_ should be
524    * 3. accumulating the adjoints into the varis pointed to by elements of
525    * x_vis_ using accumulate_adjoints
526    *
527    * This operation may be called multiple times during the life of the vari
528    */
chainstan::math::adj_jac_vari529   void chain() {
530     FReturnType y_adj;
531 
532     internal::build_y_adj(y_vi_, M_, y_adj);
533     auto y_adj_jacs = f_.multiply_adjoint_jacobian(is_var_, y_adj);
534 
535     internal::apply(
536         [this](auto&&... args) { this->accumulate_adjoints(args...); },
537         y_adj_jacs);
538   }
539 };
540 
541 /**
542  * Return the result of applying the function defined by a nullary construction
543  * of F to the specified input argument
544  *
545  * adj_jac_apply makes it possible to write efficient reverse-mode
546  * autodiff code without ever touching Stan's autodiff internals
547  *
548  * Mathematically, to use a function in reverse mode autodiff, you need to be
549  * able to evaluate the function (y = f(x)) and multiply the Jacobian of that
550  * function (df(x)/dx) by a vector.
551  *
552  * As an example, pretend there exists some large, complicated function, L(x1,
553  * x2), which contains our smaller function f(x1, x2). The goal of autodiff is
554  * to compute the partials dL/dx1 and dL/dx2. If we break the large function
555  * into pieces:
556  *
557  * y = f(x1, x2)
558  * L = g(y)
559  *
560  * If we were given dL/dy we could compute dL/dx1 by the product dL/dy * dy/dx1
561  * or dL/dx2 by the product dL/dy * dy/dx2
562  *
563  * Because y = f(x1, x2), dy/dx1 is just df(x1, x2)/dx1, the Jacobian of the
564  * function we're trying to define with x2 held fixed. A similar thing happens
565  * for dy/dx2. In vector form,
566  *
567  * dL/dx1 = (dL/dy)' * df(x1, x2)/dx1 and
568  * dL/dx2 = (dL/dy)' * df(x1, x2)/dx2
569  *
570  * So implementing f(x1, x2) and the products above are all that is required
571  * mathematically to implement reverse-mode autodiff for a function.
572  *
573  * adj_jac_apply takes as a template argument a functor F that supplies the
574  * non-static member functions (leaving exact template arguments off):
575  *
576  * (required) Eigen::VectorXd operator()(const std::array<bool, size>&
577  * needs_adj, const T1& x1..., const T2& x2, ...)
578  *
579  * where there can be any number of input arguments x1, x2, ... and T1, T2, ...
580  * can be either doubles or any Eigen::Matrix type with double scalar values.
581  * needs_adj is an array of size equal to the number of input arguments
582  * indicating whether or not the adjoint^T Jacobian product must be computed for
583  * each input argument. This argument is passed to operator() so that any
584  * unnecessary preparatory calculations for multiply_adjoint_jacobian can be
585  * avoided if possible.
586  *
587  * (required) std::tuple<T1, T2, ...> multiply_adjoint_jacobian(const
588  * std::array<bool, size>& needs_adj, const Eigen::VectorXd& adj)
589  *
590  * where T1, T2, etc. are the same types as in operator(), needs_adj is the same
591  * as in operator(), and adj is the vector dL/dy.
592  *
593  * operator() is responsible for computing f(x) and multiply_adjoint_jacobian is
594  * responsible for computing the necessary adjoint transpose Jacobian products
595  * (which frequently does not require the calculation of the full Jacobian).
596  *
597  * operator() will be called before multiply_adjoint_jacobian is called, and is
598  * only called once in the lifetime of the functor multiply_adjoint_jacobian is
599  * called after operator() and may be called multiple times for any single
600  * functor
601  *
602  * The functor supplied to adj_jac_apply must be careful to allocate any
603  * variables it defines in the autodiff arena because its destructor will
604  * never be called and memory will leak if allocated anywhere else.
605  *
606  * Targs (the input argument types) can be any mix of doubles, vars, ints,
607  * std::vectors with double, var, or int scalar components, or
608  * Eigen::Matrix s of any shape with var or double scalar components
609  *
610  * @tparam F functor to be connected to the autodiff stack
611  * @tparam Targs types of arguments to pass to functor
612  * @param args input to the functor
613  * @return the result of the specified operation wrapped up in vars
614  */
615 template <typename F, typename... Targs>
adj_jac_apply(const Targs &...args)616 auto adj_jac_apply(const Targs&... args) {
617   auto vi = new adj_jac_vari<F, Targs...>();
618 
619   return (*vi)(args...);
620 }
621 
622 }  // namespace math
623 }  // namespace stan
624 #endif
625