1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_ADLOC_FORWARD
11#define EIGEN_ADLOC_FORWARD
12
13//--------------------------------------------------------------------------------
14//
15// This file provides support for adolc's adouble type in forward mode.
16// ADOL-C is a C++ automatic differentiation library,
17// see https://projects.coin-or.org/ADOL-C for more information.
18//
19// Note that the maximal number of directions is controlled by
20// the preprocessor token NUMBER_DIRECTIONS. The default is 2.
21//
22//--------------------------------------------------------------------------------
23
24#define ADOLC_TAPELESS
25#ifndef NUMBER_DIRECTIONS
26# define NUMBER_DIRECTIONS 2
27#endif
28#include <adolc/adtl.h>
29
30// adolc defines some very stupid macros:
31#if defined(malloc)
32# undef malloc
33#endif
34
35#if defined(calloc)
36# undef calloc
37#endif
38
39#if defined(realloc)
40# undef realloc
41#endif
42
43#include <Eigen/Core>
44
45namespace Eigen {
46
47/**
48  * \defgroup AdolcForward_Module Adolc forward module
49  * This module provides support for adolc's adouble type in forward mode.
50  * ADOL-C is a C++ automatic differentiation library,
51  * see https://projects.coin-or.org/ADOL-C for more information.
52  * It mainly consists in:
53  *  - a struct Eigen::NumTraits<adtl::adouble> specialization
54  *  - overloads of internal::* math function for adtl::adouble type.
55  *
56  * Note that the maximal number of directions is controlled by
57  * the preprocessor token NUMBER_DIRECTIONS. The default is 2.
58  *
59  * \code
60  * #include <unsupported/Eigen/AdolcSupport>
61  * \endcode
62  */
63  //@{
64
65} // namespace Eigen
66
67// Eigen's require a few additional functions which must be defined in the same namespace
68// than the custom scalar type own namespace
69namespace adtl {
70
71inline const adouble& conj(const adouble& x)  { return x; }
72inline const adouble& real(const adouble& x)  { return x; }
73inline adouble imag(const adouble&)    { return 0.; }
74inline adouble abs(const adouble&  x)  { return fabs(x); }
75inline adouble abs2(const adouble& x)  { return x*x; }
76
77}
78
79namespace Eigen {
80
81template<> struct NumTraits<adtl::adouble>
82    : NumTraits<double>
83{
84  typedef adtl::adouble Real;
85  typedef adtl::adouble NonInteger;
86  typedef adtl::adouble Nested;
87  enum {
88    IsComplex = 0,
89    IsInteger = 0,
90    IsSigned = 1,
91    RequireInitialization = 1,
92    ReadCost = 1,
93    AddCost = 1,
94    MulCost = 1
95  };
96};
97
98template<typename Functor> class AdolcForwardJacobian : public Functor
99{
100  typedef adtl::adouble ActiveScalar;
101public:
102
103  AdolcForwardJacobian() : Functor() {}
104  AdolcForwardJacobian(const Functor& f) : Functor(f) {}
105
106  // forward constructors
107  template<typename T0>
108  AdolcForwardJacobian(const T0& a0) : Functor(a0) {}
109  template<typename T0, typename T1>
110  AdolcForwardJacobian(const T0& a0, const T1& a1) : Functor(a0, a1) {}
111  template<typename T0, typename T1, typename T2>
112  AdolcForwardJacobian(const T0& a0, const T1& a1, const T1& a2) : Functor(a0, a1, a2) {}
113
114  typedef typename Functor::InputType InputType;
115  typedef typename Functor::ValueType ValueType;
116  typedef typename Functor::JacobianType JacobianType;
117
118  typedef Matrix<ActiveScalar, InputType::SizeAtCompileTime, 1> ActiveInput;
119  typedef Matrix<ActiveScalar, ValueType::SizeAtCompileTime, 1> ActiveValue;
120
121  void operator() (const InputType& x, ValueType* v, JacobianType* _jac) const
122  {
123    eigen_assert(v!=0);
124    if (!_jac)
125    {
126      Functor::operator()(x, v);
127      return;
128    }
129
130    JacobianType& jac = *_jac;
131
132    ActiveInput ax = x.template cast<ActiveScalar>();
133    ActiveValue av(jac.rows());
134
135    for (int j=0; j<jac.cols(); j++)
136      for (int i=0; i<jac.cols(); i++)
137        ax[i].setADValue(j, i==j ? 1 : 0);
138
139    Functor::operator()(ax, &av);
140
141    for (int i=0; i<jac.rows(); i++)
142    {
143      (*v)[i] = av[i].getValue();
144      for (int j=0; j<jac.cols(); j++)
145        jac.coeffRef(i,j) = av[i].getADValue(j);
146    }
147  }
148protected:
149
150};
151
152//@}
153
154}
155
156#endif // EIGEN_ADLOC_FORWARD
157