Removed #ifdef blocks and documented the AD process by numbering the methods in the order they are called
							parent
							
								
									7989a8c0dc
								
							
						
					
					
						commit
						e2e29dac68
					
				|  | @ -106,7 +106,7 @@ struct UseBlockIf<false, Derived> { | |||
| }; | ||||
| } | ||||
| 
 | ||||
| /// Handle Leaf Case: reverseAD ends here, by writing a matrix into Jacobians
 | ||||
| /// Handle Leaf Case: reverse AD ends here, by writing a matrix into Jacobians
 | ||||
| template<typename Derived> | ||||
| void handleLeafCase(const Eigen::MatrixBase<Derived>& dTdA, | ||||
|     JacobianMap& jacobians, Key key) { | ||||
|  | @ -186,28 +186,28 @@ public: | |||
|     } | ||||
|   } | ||||
|   /**
 | ||||
|    *  *** This is the main entry point for reverseAD, called from Expression *** | ||||
|    *  *** This is the main entry point for reverse AD, called from Expression *** | ||||
|    * Called only once, either inserts I into Jacobians (Leaf) or starts AD (Function) | ||||
|    */ | ||||
|   typedef Eigen::Matrix<double, Dim, Dim> JacobianTT; | ||||
|   void startReverseAD(JacobianMap& jacobians) const { | ||||
|   void startReverseAD1(JacobianMap& jacobians) const { | ||||
|     if (kind == Leaf) { | ||||
|       // This branch will only be called on trivial Leaf expressions, i.e. Priors
 | ||||
|       static const JacobianTT I = JacobianTT::Identity(); | ||||
|       handleLeafCase(I, jacobians, content.key); | ||||
|     } else if (kind == Function) | ||||
|       // This is the more typical entry point, starting the AD pipeline
 | ||||
|       // Inside the startReverseAD that the correctly dimensioned pipeline is chosen.
 | ||||
|       content.ptr->startReverseAD(jacobians); | ||||
|       // Inside startReverseAD2 the correctly dimensioned pipeline is chosen.
 | ||||
|       content.ptr->startReverseAD2(jacobians); | ||||
|   } | ||||
|   // Either add to Jacobians (Leaf) or propagate (Function)
 | ||||
|   template<typename DerivedMatrix> | ||||
|   void reverseAD(const Eigen::MatrixBase<DerivedMatrix> & dTdA, | ||||
|   void reverseAD1(const Eigen::MatrixBase<DerivedMatrix> & dTdA, | ||||
|       JacobianMap& jacobians) const { | ||||
|     if (kind == Leaf) | ||||
|       handleLeafCase(dTdA, jacobians, content.key); | ||||
|     else if (kind == Function) | ||||
|       content.ptr->reverseAD(dTdA, jacobians); | ||||
|       content.ptr->reverseAD2(dTdA, jacobians); | ||||
|   } | ||||
| 
 | ||||
|   /// Define type so we can apply it as a meta-function
 | ||||
|  | @ -470,10 +470,10 @@ struct FunctionalBase: ExpressionNode<T> { | |||
|   struct Record { | ||||
|     void print(const std::string& indent) const { | ||||
|     } | ||||
|     void startReverseAD(JacobianMap& jacobians) const { | ||||
|     void startReverseAD4(JacobianMap& jacobians) const { | ||||
|     } | ||||
|     template<typename SomeMatrix> | ||||
|     void reverseAD(const SomeMatrix & dFdT, JacobianMap& jacobians) const { | ||||
|     void reverseAD4(const SomeMatrix & dFdT, JacobianMap& jacobians) const { | ||||
|     } | ||||
|   }; | ||||
|   /// Construct an execution trace for reverse AD
 | ||||
|  | @ -505,9 +505,9 @@ struct JacobianTrace { | |||
|   typename Jacobian<T, A>::type dTdA; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Recursive Definition of Functional ExpressionNode | ||||
|  */ | ||||
| // Recursive Definition of Functional ExpressionNode
 | ||||
| // The reason we inherit from Argument<T, A, N> is because we can then
 | ||||
| // case to this unique signature to retrieve the expression at any level
 | ||||
| template<class T, class A, class Base> | ||||
| struct GenerateFunctionalNode: Argument<T, A, Base::N + 1>, Base { | ||||
| 
 | ||||
|  | @ -528,7 +528,9 @@ struct GenerateFunctionalNode: Argument<T, A, Base::N + 1>, Base { | |||
|     This::expression->dims(map); | ||||
|   } | ||||
| 
 | ||||
|   /// Recursive Record Class for Functional Expressions
 | ||||
|   // Recursive Record Class for Functional Expressions
 | ||||
|   // The reason we inherit from JacobianTrace<T, A, N> is because we can then
 | ||||
|   // case to this unique signature to retrieve the value/trace at any level
 | ||||
|   struct Record: JacobianTrace<T, A, N>, Base::Record { | ||||
| 
 | ||||
|     typedef T return_type; | ||||
|  | @ -543,17 +545,26 @@ struct GenerateFunctionalNode: Argument<T, A, Base::N + 1>, Base { | |||
|     } | ||||
| 
 | ||||
|     /// Start the reverse AD process
 | ||||
|     void startReverseAD(JacobianMap& jacobians) const { | ||||
|       Base::Record::startReverseAD(jacobians); | ||||
|       This::trace.reverseAD(This::dTdA, jacobians); | ||||
|     void startReverseAD4(JacobianMap& jacobians) const { | ||||
|       Base::Record::startReverseAD4(jacobians); | ||||
|       // This is the crucial point where the size of the AD pipeline is selected.
 | ||||
|       // One pipeline is started for each argument, but the number of rows in each
 | ||||
|       // pipeline is the same, namely the dimension of the output argument T.
 | ||||
|       // For example, if the entire expression is rooted by a binary function
 | ||||
|       // yielding a 2D result, then the matrix dTdA will have 2 rows.
 | ||||
|       // ExecutionTrace::reverseAD1 just passes this on to CallRecord::reverseAD2
 | ||||
|       // which calls the correctly sized CallRecord::reverseAD3, which in turn
 | ||||
|       // calls reverseAD4 below.
 | ||||
|       This::trace.reverseAD1(This::dTdA, jacobians); | ||||
|     } | ||||
| 
 | ||||
|     /// Given df/dT, multiply in dT/dA and continue reverse AD process
 | ||||
|     // Cols is always known at compile time
 | ||||
|     template<int Rows, int Cols> | ||||
|     void reverseAD(const Eigen::Matrix<double, Rows, Cols> & dFdT, | ||||
|     void reverseAD4(const Eigen::Matrix<double, Rows, Cols> & dFdT, | ||||
|         JacobianMap& jacobians) const { | ||||
|       Base::Record::reverseAD(dFdT, jacobians); | ||||
|       This::trace.reverseAD(dFdT * This::dTdA, jacobians); | ||||
|       Base::Record::reverseAD4(dFdT, jacobians); | ||||
|       This::trace.reverseAD1(dFdT * This::dTdA, jacobians); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|  | @ -614,8 +625,8 @@ struct FunctionalNode { | |||
|     struct Record: public internal::CallRecordImplementor<Record, | ||||
|         traits::dimension<T>::value>, public Base::Record { | ||||
|       using Base::Record::print; | ||||
|       using Base::Record::startReverseAD; | ||||
|       using Base::Record::reverseAD; | ||||
|       using Base::Record::startReverseAD4; | ||||
|       using Base::Record::reverseAD4; | ||||
| 
 | ||||
|       virtual ~Record() { | ||||
|       } | ||||
|  |  | |||
|  | @ -209,7 +209,7 @@ private: | |||
|     ExecutionTraceStorage traceStorage[size]; | ||||
|     ExecutionTrace<T> trace; | ||||
|     T value(traceExecution(values, trace, traceStorage)); | ||||
|     trace.startReverseAD(jacobians); | ||||
|     trace.startReverseAD1(jacobians); | ||||
|     return value; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,12 +32,6 @@ class JacobianMap; | |||
| // forward declaration
 | ||||
| 
 | ||||
| //-----------------------------------------------------------------------------
 | ||||
| /**
 | ||||
|  * MaxVirtualStaticRows defines how many separate virtual reverseAD with specific | ||||
|  * static rows (1..MaxVirtualStaticRows) methods will be part of the CallRecord interface. | ||||
|  */ | ||||
| #define MaxVirtualStaticRows 4 | ||||
| 
 | ||||
| namespace internal { | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -57,7 +51,8 @@ struct ConvertToVirtualFunctionSupportedMatrixType { | |||
| template<> | ||||
| struct ConvertToVirtualFunctionSupportedMatrixType<false> { | ||||
|   template<typename Derived> | ||||
|   static const Eigen::Matrix<double, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> convert( | ||||
|   static const Eigen::Matrix<double, Derived::RowsAtCompileTime, | ||||
|       Derived::ColsAtCompileTime> convert( | ||||
|       const Eigen::MatrixBase<Derived> & x) { | ||||
|     return x; | ||||
|   } | ||||
|  | @ -72,73 +67,68 @@ struct ConvertToVirtualFunctionSupportedMatrixType<false> { | |||
| } // namespace internal
 | ||||
| 
 | ||||
| /**
 | ||||
|  * The CallRecord class stores the Jacobians of applying a function | ||||
|  * with respect to each of its arguments. It also stores an execution trace | ||||
|  * (defined below) for each of its arguments. | ||||
|  * | ||||
|  * It is implemented in the function-style ExpressionNode's nested Record class below. | ||||
|  * The CallRecord is an abstract base class for the any class that stores | ||||
|  * the Jacobians of applying a function with respect to each of its arguments, | ||||
|  * as well as an execution trace for each of its arguments. | ||||
|  */ | ||||
| template<int Cols> | ||||
| struct CallRecord { | ||||
| 
 | ||||
|   // Print entire record, recursively
 | ||||
|   inline void print(const std::string& indent) const { | ||||
|     _print(indent); | ||||
|   } | ||||
| 
 | ||||
|   inline void startReverseAD(JacobianMap& jacobians) const { | ||||
|     _startReverseAD(jacobians); | ||||
|   // Main entry point for the reverse AD process of a functional expression.
 | ||||
|   // Called *once* by the main AD entry point, ExecutionTrace::startReverseAD1
 | ||||
|   // This function then calls ExecutionTrace::reverseAD for every argument
 | ||||
|   // which will in turn call the reverseAD method below.
 | ||||
|   // This non-virtual function _startReverseAD3, implemented in derived
 | ||||
|   inline void startReverseAD2(JacobianMap& jacobians) const { | ||||
|     _startReverseAD3(jacobians); | ||||
|   } | ||||
| 
 | ||||
|   // Dispatch the reverseAD2 calls issued by ExecutionTrace::reverseAD1
 | ||||
|   // Here we convert to dynamic if the
 | ||||
|   template<typename Derived> | ||||
|   inline void reverseAD(const Eigen::MatrixBase<Derived> & dFdT, | ||||
|   inline void reverseAD2(const Eigen::MatrixBase<Derived> & dFdT, | ||||
|       JacobianMap& jacobians) const { | ||||
|     _reverseAD( | ||||
|          internal::ConvertToVirtualFunctionSupportedMatrixType< | ||||
|              (Derived::RowsAtCompileTime > MaxVirtualStaticRows) | ||||
|            >::convert(dFdT), | ||||
|          jacobians | ||||
|        ); | ||||
|     _reverseAD3( | ||||
|         internal::ConvertToVirtualFunctionSupportedMatrixType< | ||||
|             (Derived::RowsAtCompileTime > 5)>::convert(dFdT), | ||||
|         jacobians); | ||||
|   } | ||||
| 
 | ||||
|   inline void reverseAD(const Matrix & dFdT, JacobianMap& jacobians) const { | ||||
|     _reverseAD(dFdT, jacobians); | ||||
|   } | ||||
| // TODO: remove once Hannes agrees this is never called as handled by above
 | ||||
| //  inline void reverseAD2(const Matrix & dFdT, JacobianMap& jacobians) const {
 | ||||
| //    _reverseAD3(dFdT, jacobians);
 | ||||
| //  }
 | ||||
| 
 | ||||
|   virtual ~CallRecord() { | ||||
|   } | ||||
| 
 | ||||
| private: | ||||
|   virtual void _print(const std::string& indent) const = 0; | ||||
|   virtual void _startReverseAD(JacobianMap& jacobians) const = 0; | ||||
| 
 | ||||
|   virtual void _reverseAD(const Matrix & dFdT, JacobianMap& jacobians) const = 0; | ||||
|   virtual void _reverseAD( | ||||
|   virtual void _print(const std::string& indent) const = 0; | ||||
|   virtual void _startReverseAD3(JacobianMap& jacobians) const = 0; | ||||
| 
 | ||||
|   virtual void _reverseAD3(const Matrix & dFdT, | ||||
|       JacobianMap& jacobians) const = 0; | ||||
| 
 | ||||
|   virtual void _reverseAD3( | ||||
|       const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const = 0; | ||||
| #if MaxVirtualStaticRows >= 1 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 1, Cols> & dFdT, | ||||
| 
 | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 1, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const = 0; | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 2 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 2, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 2, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const = 0; | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 3 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 3, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 3, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const = 0; | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 4 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 4, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 4, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const = 0; | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 5 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 5, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 5, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const = 0; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| namespace internal { | ||||
|  | @ -149,59 +139,48 @@ namespace internal { | |||
| template<typename Derived, int Cols> | ||||
| struct CallRecordImplementor: public CallRecord<Cols> { | ||||
| private: | ||||
| 
 | ||||
|   const Derived & derived() const { | ||||
|     return static_cast<const Derived&>(*this); | ||||
|   } | ||||
| 
 | ||||
|   virtual void _print(const std::string& indent) const { | ||||
|     derived().print(indent); | ||||
|   } | ||||
|   virtual void _startReverseAD(JacobianMap& jacobians) const { | ||||
|     derived().startReverseAD(jacobians); | ||||
| 
 | ||||
|   virtual void _startReverseAD3(JacobianMap& jacobians) const { | ||||
|     derived().startReverseAD4(jacobians); | ||||
|   } | ||||
| 
 | ||||
|   virtual void _reverseAD(const Matrix & dFdT, JacobianMap& jacobians) const { | ||||
|     derived().reverseAD(dFdT, jacobians); | ||||
|   virtual void _reverseAD3(const Matrix & dFdT, JacobianMap& jacobians) const { | ||||
|     derived().reverseAD4(dFdT, jacobians); | ||||
|   } | ||||
|   virtual void _reverseAD( | ||||
| 
 | ||||
|   virtual void _reverseAD3( | ||||
|       const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const { | ||||
|     derived().reverseAD(dFdT, jacobians); | ||||
|     derived().reverseAD4(dFdT, jacobians); | ||||
|   } | ||||
| #if MaxVirtualStaticRows >= 1 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 1, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 1, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const { | ||||
|     derived().reverseAD(dFdT, jacobians); | ||||
|     derived().reverseAD4(dFdT, jacobians); | ||||
|   } | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 2 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 2, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 2, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const { | ||||
|     derived().reverseAD(dFdT, jacobians); | ||||
|     derived().reverseAD4(dFdT, jacobians); | ||||
|   } | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 3 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 3, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 3, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const { | ||||
|     derived().reverseAD(dFdT, jacobians); | ||||
|     derived().reverseAD4(dFdT, jacobians); | ||||
|   } | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 4 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 4, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 4, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const { | ||||
|     derived().reverseAD(dFdT, jacobians); | ||||
|     derived().reverseAD4(dFdT, jacobians); | ||||
|   } | ||||
| #endif | ||||
| #if MaxVirtualStaticRows >= 5 | ||||
|   virtual void _reverseAD( | ||||
|       const Eigen::Matrix<double, 5, Cols> & dFdT, | ||||
|   virtual void _reverseAD3(const Eigen::Matrix<double, 5, Cols> & dFdT, | ||||
|       JacobianMap& jacobians) const { | ||||
|     derived().reverseAD(dFdT, jacobians); | ||||
|     derived().reverseAD4(dFdT, jacobians); | ||||
|   } | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| } // namespace internal
 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ static const int Cols = 3; | |||
| 
 | ||||
| 
 | ||||
| int dynamicIfAboveMax(int i){ | ||||
|   if(i > MaxVirtualStaticRows){ | ||||
|   if(i > 5){ | ||||
|     return Eigen::Dynamic; | ||||
|   } | ||||
|   else return i; | ||||
|  | @ -76,20 +76,20 @@ struct Record: public internal::CallRecordImplementor<Record, Cols> { | |||
|   } | ||||
|   void print(const std::string& indent) const { | ||||
|   } | ||||
|   void startReverseAD(JacobianMap& jacobians) const { | ||||
|   void startReverseAD4(JacobianMap& jacobians) const { | ||||
|   } | ||||
| 
 | ||||
|   mutable CallConfig cc; | ||||
|  private: | ||||
|   template<typename SomeMatrix> | ||||
|   void reverseAD(const SomeMatrix & dFdT, JacobianMap& jacobians) const { | ||||
|   void reverseAD4(const SomeMatrix & dFdT, JacobianMap& jacobians) const { | ||||
|     cc.compTimeRows = SomeMatrix::RowsAtCompileTime; | ||||
|     cc.compTimeCols = SomeMatrix::ColsAtCompileTime; | ||||
|     cc.runTimeRows = dFdT.rows(); | ||||
|     cc.runTimeCols = dFdT.cols(); | ||||
|   } | ||||
| 
 | ||||
|   template<typename Derived, int Rows, int OtherCols> | ||||
|   template<typename Derived, int Rows> | ||||
|   friend struct internal::CallRecordImplementor; | ||||
| }; | ||||
| 
 | ||||
|  | @ -102,56 +102,56 @@ TEST(CallRecord, virtualReverseAdDispatching) { | |||
|   Record record; | ||||
|   { | ||||
|     const int Rows = 1; | ||||
|     record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(DynRowMat(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols)))); | ||||
|   } | ||||
|   { | ||||
|     const int Rows = 2; | ||||
|     record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(DynRowMat(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols)))); | ||||
|   } | ||||
|   { | ||||
|     const int Rows = 3; | ||||
|     record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(DynRowMat(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols)))); | ||||
|   } | ||||
|   { | ||||
|     const int Rows = MaxVirtualStaticRows; | ||||
|     record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     const int Rows = 4; | ||||
|     record.CallRecord::reverseAD2(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(DynRowMat(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols)))); | ||||
|   } | ||||
|   { | ||||
|     const int Rows = MaxVirtualStaticRows + 1; | ||||
|     record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     const int Rows = 5; | ||||
|     record.CallRecord::reverseAD2(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(DynRowMat(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols)))); | ||||
|   } | ||||
|   { | ||||
|     const int Rows = MaxVirtualStaticRows + 2; | ||||
|     record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     const int Rows = 6; | ||||
|     record.CallRecord::reverseAD2(Eigen::Matrix<double, Rows, Cols>(), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(DynRowMat(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols)))); | ||||
|     record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     record.CallRecord::reverseAD2(Eigen::MatrixXd(Rows, Cols), NJM); | ||||
|     EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols)))); | ||||
|   } | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue