GTSAM  4.0.2
C++ library for smoothing and mapping (SAM)
CallRecord.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
21 #pragma once
22 
24 
25 namespace gtsam {
26 namespace internal {
27 
33 template<bool ConvertToDynamicRows>
35  template<typename Derived>
36  static Eigen::Matrix<double, Eigen::Dynamic, Derived::ColsAtCompileTime> convert(
37  const Eigen::MatrixBase<Derived>& x) {
38  return x;
39  }
40 };
41 
42 template<>
43 struct ConvertToDynamicIf<false> {
44  template<typename Derived>
45  static const Eigen::Matrix<double, Derived::RowsAtCompileTime,
46  Derived::ColsAtCompileTime> convert(
47  const Eigen::MatrixBase<Derived> & x) {
48  return x;
49  }
50  // Most common case: just pass through matrices that are already of the right fixed-size type
51  template <int Rows, int Cols>
52  static const Eigen::Matrix<double, Rows, Cols>& convert(
53  const Eigen::Matrix<double, Rows, Cols>& x) {
54  return x;
55  }
56 };
57 
68 template<int Cols>
69 struct CallRecord {
70 
71  // Print entire record, recursively
72  inline void print(const std::string& indent) const {
73  _print(indent);
74  }
75 
76  // Main entry point for the reverse AD process of a functional expression.
77  // Called *once* by the main AD entry point, ExecutionTrace::startReverseAD1
78  // This function then calls ExecutionTrace::reverseAD for every argument
79  // which will in turn call the reverseAD method below.
80  // Calls virtual function _startReverseAD3, implemented in derived
81  inline void startReverseAD2(JacobianMap& jacobians) const {
82  _startReverseAD3(jacobians);
83  }
84 
85  // Dispatch the reverseAD2 calls issued by ExecutionTrace::reverseAD1
86  // Here we convert dFdT to a dynamic Matrix if the # rows>5, because _reverseAD3 is only
87  // specialized for fixed-size matrices up to 5 rows.
88  // The appropriate _reverseAD3 method is selected by method overloading.
89  template <typename Derived>
90  inline void reverseAD2(const Eigen::MatrixBase<Derived>& dFdT, JacobianMap& jacobians) const {
91  _reverseAD3(ConvertToDynamicIf<(Derived::RowsAtCompileTime > 5)>::convert(dFdT), jacobians);
92  }
93 
94  // This overload supports matrices with both rows and columns dynamically sized.
95  // The template version above would be slower by introducing an extra conversion
96  // to statically sized columns.
97  inline void reverseAD2(const Matrix & dFdT, JacobianMap& jacobians) const {
98  _reverseAD3(dFdT, jacobians);
99  }
100 
101  virtual ~CallRecord() {
102  }
103 
104 private:
105 
106  virtual void _print(const std::string& indent) const = 0;
107  virtual void _startReverseAD3(JacobianMap& jacobians) const = 0;
108 
109  virtual void _reverseAD3(const Matrix & dFdT,
110  JacobianMap& jacobians) const = 0;
111 
112  virtual void _reverseAD3(
113  const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT,
114  JacobianMap& jacobians) const = 0;
115 
116  virtual void _reverseAD3(const Eigen::Matrix<double, 1, Cols> & dFdT,
117  JacobianMap& jacobians) const = 0;
118  virtual void _reverseAD3(const Eigen::Matrix<double, 2, Cols> & dFdT,
119  JacobianMap& jacobians) const = 0;
120  virtual void _reverseAD3(const Eigen::Matrix<double, 3, Cols> & dFdT,
121  JacobianMap& jacobians) const = 0;
122  virtual void _reverseAD3(const Eigen::Matrix<double, 4, Cols> & dFdT,
123  JacobianMap& jacobians) const = 0;
124  virtual void _reverseAD3(const Eigen::Matrix<double, 5, Cols> & dFdT,
125  JacobianMap& jacobians) const = 0;
126 };
127 
134 
139 template<typename Derived, int Cols>
140 struct CallRecordImplementor: public CallRecord<Cols> {
141 private:
142 
143  const Derived & derived() const {
144  return static_cast<const Derived&>(*this);
145  }
146 
147  void _print(const std::string& indent) const override {
148  derived().print(indent);
149  }
150 
151  // Called from base class non-virtual inline method startReverseAD2
152  // Calls non-virtual function startReverseAD4, implemented in Derived (ExpressionNode::Record)
153  void _startReverseAD3(JacobianMap& jacobians) const override {
154  derived().startReverseAD4(jacobians);
155  }
156 
157  void _reverseAD3(const Matrix & dFdT, JacobianMap& jacobians) const override {
158  derived().reverseAD4(dFdT, jacobians);
159  }
160 
161  void _reverseAD3(
162  const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT,
163  JacobianMap& jacobians) const override {
164  derived().reverseAD4(dFdT, jacobians);
165  }
166  void _reverseAD3(const Eigen::Matrix<double, 1, Cols> & dFdT,
167  JacobianMap& jacobians) const override {
168  derived().reverseAD4(dFdT, jacobians);
169  }
170  void _reverseAD3(const Eigen::Matrix<double, 2, Cols> & dFdT,
171  JacobianMap& jacobians) const override {
172  derived().reverseAD4(dFdT, jacobians);
173  }
174  void _reverseAD3(const Eigen::Matrix<double, 3, Cols> & dFdT,
175  JacobianMap& jacobians) const override {
176  derived().reverseAD4(dFdT, jacobians);
177  }
178  void _reverseAD3(const Eigen::Matrix<double, 4, Cols> & dFdT,
179  JacobianMap& jacobians) const override {
180  derived().reverseAD4(dFdT, jacobians);
181  }
182  void _reverseAD3(const Eigen::Matrix<double, 5, Cols> & dFdT,
183  JacobianMap& jacobians) const override {
184  derived().reverseAD4(dFdT, jacobians);
185  }
186 };
187 
188 } // namespace internal
189 } // gtsam
Definition: CallRecord.h:34
JacobianMap for returning derivatives from expressions.
Definition: JacobianMap.h:32
Definition: CallRecord.h:69
GTSAM_EXPORT void print(const Matrix &A, const std::string &s, std::ostream &stream)
Definition: chartTesting.h:28
const int CallRecordMaxVirtualStaticRows
Definition: CallRecord.h:133
Definition: CallRecord.h:140