ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tiny_ad.hpp
Go to the documentation of this file.
1 // Copyright (C) 2016 Kasper Kristensen
2 // License: GPL-2
3 
4 #ifndef TINY_AD_H
5 #define TINY_AD_H
6 
7 /* Standalone ? */
8 #ifndef R_RCONFIG_H
9 #include <cmath>
10 #include <iostream>
11 #define CSKIP(x) x
12 #endif
13 
14 /* Select the vector class to use (Default: tiny_vec) */
15 #if defined(TINY_AD_USE_STD_VALARRAY)
16 #include "tiny_valarray.hpp"
17 #define TINY_VECTOR(type,size) tiny_vector<type, size>
18 #elif defined(TINY_AD_USE_EIGEN_VEC)
19 #include <Eigen/Dense>
20 #define TINY_VECTOR(type,size) Eigen::Array<type, size, 1>
21 #else
22 #include "tiny_vec.hpp"
23 #define TINY_VECTOR(type,size) tiny_vec<type, size>
24 #endif
25 
26 namespace tiny_ad {
27  template<class Type, class Vector>
28  struct ad {
29  Type value;
30  Vector deriv;
31  ad(){}
32  ad(Type v, Vector d){value = v; deriv = d;}
33  ad(double v) {value = v; deriv.setZero();}
34  ad operator+ (const ad &other) const{
35  return ad(value + other.value,
36  deriv + other.deriv);
37  }
38  ad operator+ () const{
39  return *this;
40  }
41  ad operator- (const ad &other) const{
42  return ad(value - other.value,
43  deriv - other.deriv);
44  }
45  ad operator- () const{
46  return ad(-value, -deriv);
47  }
48  ad operator* (const ad &other) const{
49  return ad(value * other.value,
50  value * other.deriv +
51  deriv * other.value);
52  }
53  ad operator/ (const ad &other) const{
54  Type res = value / other.value;
55  return ad(res,
56  (deriv - res * other.deriv) /
57  other.value );
58  }
59  /* Comparison operators */
60 #define COMPARISON_OPERATOR(OP) \
61  template<class other> \
62  bool operator OP (const other &x) const{ \
63  return (value OP x); \
64  }
71 #undef COMPARISON_OPERATOR
72  /* Combine ad with other types (constants) */
73  ad operator+ (const double &x) const{
74  return ad(value + x, deriv);
75  }
76  ad operator- (const double &x) const{
77  return ad(value - x, deriv);
78  }
79  ad operator* (const double &x) const{
80  return ad(value * x, deriv * x);
81  }
82  ad operator/ (const double &x) const{
83  return ad(value / x, deriv / x);
84  }
85  /* Note: 'this' and 'other' may point to the same object */
86  ad& operator+=(const ad &other){
87  value += other.value;
88  deriv += other.deriv;
89  return *this;
90  }
91  ad& operator-=(const ad &other){
92  value -= other.value;
93  deriv -= other.deriv;
94  return *this;
95  }
96  ad& operator*=(const ad &other){
97  if (this != &other) {
98  deriv *= other.value;
99  deriv += other.deriv * value;
100  value *= other.value;
101  } else {
102  deriv *= value * 2.;
103  value *= value;
104  }
105  return *this;
106  }
107  ad& operator/=(const ad &other){
108  value /= other.value;
109  deriv -= other.deriv * value;
110  deriv /= other.value;
111  return *this;
112  }
113  };
114  /* Binary operators where a constant is first argument */
115  template<class T, class V>
116  ad<T, V> operator+ (const double &x, const ad<T, V> &y) {
117  return y + x;
118  }
119  template<class T, class V>
120  ad<T, V> operator- (const double &x, const ad<T, V> &y) {
121  return -(y - x);
122  }
123  template<class T, class V>
124  ad<T, V> operator* (const double &x, const ad<T, V> &y) {
125  return y * x;
126  }
127  template<class T, class V>
128  ad<T, V> operator/ (const double &x, const ad<T, V> &y) {
129  T value = x / y.value;
130  return ad<T, V>(value, T(-value / y.value) * y.deriv);
131  }
132  /* Unary operators with trivial derivatives */
133 #define UNARY_MATH_ZERO_DERIV(F) \
134  template<class T, class V> \
135  double F (const ad<T, V> &x){ \
136  return F(x.value); \
137  }
138  using ::floor; using ::ceil;
139  using ::trunc; using ::round;
140  UNARY_MATH_ZERO_DERIV(floor)
142  UNARY_MATH_ZERO_DERIV(trunc)
143  UNARY_MATH_ZERO_DERIV(round)
144  template<class T>
145  double sign(const T &x){return (x > 0) - (x < 0);}
146  //bool isfinite(const double &x)CSKIP( {return std::isfinite(x);} )
147  using std::isfinite;
148  template<class T, class V>
149  bool isfinite(const ad<T, V> &x){return isfinite(x.value);}
150 #undef UNARY_MATH_ZERO_DERIV
151  /* Unary operators with non-trivial derivatives */
152 #define UNARY_MATH_DERIVATIVE(F,DF) \
153  template<class T, class V> \
154  ad<T, V> F (const ad<T, V> &x){ \
155  return ad<T, V>(F (x.value), \
156  T(DF(x.value)) * x.deriv); \
157  }
162  template<class T> T D_tan(const T &x) {
163  T y = cos(x); return 1. / (y * y);
164  }
165  template<class T> T D_tanh(const T &x) {
166  T y = cosh(x); return 1. / (y * y);
167  }
176  UNARY_MATH_DERIVATIVE(sqrt, 0.5/sqrt)
178  using ::expm1; using ::log1p;
179  UNARY_MATH_DERIVATIVE(expm1, exp)
180  template<class T> T D_log1p(const T &x) {return 1. / (x + 1.);}
182  /* asin, acos, atan */
183  using ::asin; using ::acos; using ::atan;
184  template<class T> T D_asin(const T &x) {
185  return 1. / sqrt(1. - x * x);
186  }
187  template<class T> T D_acos(const T &x) {
188  return -1. / sqrt(1. - x * x);
189  }
190  template<class T> T D_atan(const T &x) {
191  return 1. / (1. + x * x);
192  }
196 #undef UNARY_MATH_DERIVATIVE
197  /* A few more ... */
198  template<class T, class V>
199  ad<T, V> pow (const ad<T, V> &x, const ad<T, V> &y){
200  return exp(y * log(x));
201  }
202  using ::pow;
203  template<class T, class V>
204  ad<T, V> pow (const ad<T, V> &x, const double &y){
205  return ad<T, V> (pow(x.value, y), // Note: x.value could be 0
206  T( y * pow(x.value, y - 1.) ) * x.deriv);
207  }
208  /* Comparison operators where a constant is first argument */
209 #define COMPARISON_OPERATOR_FLIP(OP1, OP2) \
210  template<class T, class V> \
211  bool operator OP1 (const double &x, const ad<T, V> &y) { \
212  return y.operator OP2(x); \
213  }
220 #undef COMPARISON_OPERATOR_FLIP
221  /* R-specific derivatives (rely on Rmath)*/
222 #ifdef R_RCONFIG_H
223  extern "C" {
224  /* See 'R-API: entry points to C-code' (Writing R-extensions) */
225  double Rf_lgammafn(double);
226  double Rf_psigamma(double, double);
227  }
228  template<int deriv>
229  double lgamma(const double &x) {
230  return Rf_psigamma(x, deriv-1);
231  }
232  template<>
233  double lgamma<0>(const double &x) CSKIP( {return Rf_lgammafn(x);} )
234  double lgamma(const double &x) CSKIP( {return lgamma<0>(x);} )
235  template<int deriv, class T, class V>
236  ad<T, V> lgamma (const ad<T, V> &x){
237  return ad<T, V> (lgamma< deriv >(x.value),
238  T(lgamma< deriv + 1 >(x.value)) * x.deriv);
239  }
240  template<class T, class V>
241  ad<T, V> lgamma (const ad<T, V> &x){
242  return lgamma<0>(x);
243  }
244 #endif
245  /* Print method */
246  template<class T, class V>
247  std::ostream &operator<<(std::ostream &os, const ad<T, V> &x) {
248  os << "{";
249  os << " value=" << x.value;
250  os << " deriv=" << x.deriv;
251  os << "}";
252  return os;
253  }
254 
255  /* Interface to higher order derivatives. Example:
256 
257  typedef tiny_ad::variable<3, 2> Float; // Track 3rd order derivs wrt. 2 parameters
258  Float a (1.23, 0); // Let a = 1.23 have parameter index 0
259  Float b (2.34, 1); // Let b = 2.34 have parameter index 1
260  Float y = sin(a + b); // Run the algorithm
261  y.getDeriv(); // Get all 3rd order derivatives
262  */
263 #define VARIABLE(order, nvar, scalartype) variable<order, nvar, scalartype>
264  template<int order, int nvar, class Double=double>
265  struct variable : ad< VARIABLE(order-1, nvar, Double),
266  TINY_VECTOR( VARIABLE(order-1, nvar, Double) , nvar) > {
267  typedef ad< VARIABLE(order-1, nvar, Double),
268  TINY_VECTOR(VARIABLE(order-1, nvar, Double), nvar) > Base;
269  typedef variable<order-1, nvar, Double> Type;
270  static const int result_size = nvar * Type::result_size;
271  variable() { /* Do not zero-initialize */ }
272  variable(Base x) : Base(x) {}
273  variable(double x) : Base(x) {}
274  variable(double x, int id) : Base(x) {
275  setid(id);
276  }
277  template<class Constant>
278  variable(Constant x) {
279  Base::value = x; Base::deriv.setZero();
280  }
281  template<class Constant>
282  variable(Constant x, int id) {
283  Base::value = x; Base::deriv.setZero();
284  setid(id);
285  }
286  void setid(int i0, int count = 0){
287  this->value.setid(i0, count);
288  this->deriv[i0].setid(i0, count + 1);
289  }
290  TINY_VECTOR(Double, result_size) getDeriv(){
291  TINY_VECTOR(Double, result_size) ans;
292  int stride = result_size / nvar;
293  for(int i=0; i<nvar; i++)
294  ans.segment(i * stride, stride) = this->deriv[i].getDeriv();
295  return ans;
296  }
297  };
298 #undef VARIABLE
299  template<int nvar, class Double>
300  struct variable<1, nvar, Double> : ad<Double, TINY_VECTOR(Double,nvar) >{
302  static const int result_size = nvar;
303  variable() { /* Do not zero-initialize */ }
304  variable(Base x) : Base(x) {}
305  variable(double x) : Base(x) {}
306  variable(double x, int id) : Base(x) {
307  setid(id);
308  }
309  template<class Constant>
310  variable(Constant x) {
311  Base::value = x; Base::deriv.setZero();
312  }
313  template<class Constant>
314  variable(Constant x, int id) {
315  Base::value = x; Base::deriv.setZero();
316  setid(id);
317  }
318  void setid(int i0, int count = 0){
319  if(count == 0)
320  this->deriv[i0] = 1.0;
321  if(count == 1)
322  this->value = 1.0;
323  }
324  TINY_VECTOR(Double, nvar) getDeriv(){
325  return this->deriv;
326  }
327  };
328 #undef TINY_VECTOR
329 } // End namespace tiny_ad
330 
331 #endif
d3_array tan(const d3_array &arr3)
Returns d3_array results with computed tan from elements in arr3.
Definition: d3arr2a.cpp:73
variable(double x, int id)
Definition: tiny_ad.hpp:274
ad operator-() const
Definition: tiny_ad.hpp:45
ad< VARIABLE(order-1, nvar, Double), TINY_VECTOR(VARIABLE(order-1, nvar, Double), nvar) > Base
Definition: tiny_ad.hpp:268
dvector tanh(const dvector &vec)
Returns dvector with hyperbolic tangent for each value of vec.
Definition: dvect6.cpp:126
ad & operator+=(const ad &other)
Definition: tiny_ad.hpp:86
void setid(int i0, int count=0)
Definition: tiny_ad.hpp:286
#define x
#define COMPARISON_OPERATOR_FLIP(OP1, OP2)
Definition: tiny_ad.hpp:209
#define COMPARISON_OPERATOR(OP)
Definition: tiny_ad.hpp:60
T D_tan(const T &x)
Definition: tiny_ad.hpp:162
dvariable lgamma(const prevariable &v)
Definition: dtweedie.cpp:23
T D_log1p(const T &x)
Definition: tiny_ad.hpp:180
variable(Constant x)
Definition: tiny_ad.hpp:278
df1_one_variable atan(const df1_one_variable &x)
Definition: df11fun.cpp:312
d3_array sin(const d3_array &arr3)
Returns d3_array results with computed sin from elements in arr3.
Definition: d3arr2a.cpp:43
dvector cosh(const dvector &vec)
Returns dvector with hyperbolic cosine for each value of vec.
Definition: dvect6.cpp:105
ad< T, V > operator+(const double &x, const ad< T, V > &y)
Definition: tiny_ad.hpp:116
df1_two_variable fabs(const df1_two_variable &x)
Definition: df12fun.cpp:891
bool isfinite(const ad< T, V > &x)
Definition: tiny_ad.hpp:149
ad< Double, TINY_VECTOR(Double, nvar) > Base
Definition: tiny_ad.hpp:301
Vector deriv
Definition: tiny_ad.hpp:30
static const int result_size
Definition: tiny_ad.hpp:270
ad< T, V > operator-(const double &x, const ad< T, V > &y)
Definition: tiny_ad.hpp:120
Type value
Definition: tiny_ad.hpp:29
ad & operator*=(const ad &other)
Definition: tiny_ad.hpp:96
d3_array sqrt(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2c.cpp:11
T D_asin(const T &x)
Definition: tiny_ad.hpp:184
#define UNARY_MATH_DERIVATIVE(F, DF)
Definition: tiny_ad.hpp:152
ad< T, V > operator*(const double &x, const ad< T, V > &y)
Definition: tiny_ad.hpp:124
ad & operator-=(const ad &other)
Definition: tiny_ad.hpp:91
#define VARIABLE(order, nvar, scalartype)
Definition: tiny_ad.hpp:263
d3_array exp(const d3_array &arr3)
Returns d3_array results with computed exp from elements in arr3.
Definition: d3arr2a.cpp:28
variable(Base x)
Definition: tiny_ad.hpp:272
ad operator+() const
Definition: tiny_ad.hpp:38
ad< T, V > pow(const ad< T, V > &x, const ad< T, V > &y)
Definition: tiny_ad.hpp:199
ad< T, V > operator/(const double &x, const ad< T, V > &y)
Definition: tiny_ad.hpp:128
double sign(const T &x)
Definition: tiny_ad.hpp:145
#define UNARY_MATH_ZERO_DERIV(F)
Definition: tiny_ad.hpp:133
ad(double v)
Definition: tiny_ad.hpp:33
d3_array cos(const d3_array &arr3)
Returns d3_array results with computed cos from elements in arr3.
Definition: d3arr2a.cpp:58
T D_tanh(const T &x)
Definition: tiny_ad.hpp:165
TINY_VECTOR(Double, nvar) getDeriv()
Definition: tiny_ad.hpp:324
variable(double x)
Definition: tiny_ad.hpp:273
ad operator/(const ad &other) const
Definition: tiny_ad.hpp:53
dvector sinh(const dvector &vec)
Returns dvector with hyperbolic sine for each value of vec.
Definition: dvect6.cpp:84
ad(Type v, Vector d)
Definition: tiny_ad.hpp:32
T D_acos(const T &x)
Definition: tiny_ad.hpp:187
#define CSKIP(x)
Definition: tiny_ad.hpp:11
void setid(int i0, int count=0)
Definition: tiny_ad.hpp:318
variable(Constant x, int id)
Definition: tiny_ad.hpp:282
ad operator*(const ad &other) const
Definition: tiny_ad.hpp:48
dvector value(const df1_one_vector &v)
Definition: df11fun.cpp:69
TINY_VECTOR(Double, result_size) getDeriv()
Definition: tiny_ad.hpp:290
ad & operator/=(const ad &other)
Definition: tiny_ad.hpp:107
d3_array log(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2a.cpp:13
T D_atan(const T &x)
Definition: tiny_ad.hpp:190
dvector acos(const dvector &vec)
Returns dvector with principal value of the arc cosine of vec, expressed in radians.
Definition: dvect6.cpp:244
d3_array pow(const d3_array &m, int e)
Description not yet available.
Definition: d3arr6.cpp:17
variable< order-1, nvar, Double > Type
Definition: tiny_ad.hpp:269
dvector asin(const dvector &vec)
Returns dvector with principal value of the arc sine of vec, expressed in radians.
Definition: dvect6.cpp:229