Drake
autodiff_overloads.h
Go to the documentation of this file.
1 /// @file
2 /// Overloads for STL mathematical operations on AutoDiffScalar.
3 ///
4 /// Used via argument-dependent lookup (ADL). These functions appear
5 /// in the Eigen namespace so that ADL can automatically choose between
6 /// the STL version and the overloaded version to match the type of the
7 /// arguments. The proper use would be e.g.
8 ///
9 /// \code{.cc}
10 /// void mymethod() {
11 /// using std::isinf;
12 /// isinf(myval);
13 /// }
14 /// \endcode{}
15 ///
16 /// @note The if_then_else and cond functions for AutoDiffScalar are in
17 /// namespace drake because cond is defined in namespace drake in
18 /// "drake/common/cond.h" file.
19 
20 #pragma once
21 
22 #ifndef DRAKE_COMMON_AUTODIFF_HEADER
23 // TODO(soonho-tri): Change to #error.
24 #warning Do not directly include this file. Include "drake/common/autodiff.h".
25 #endif
26 
27 #include <cmath>
28 #include <limits>
29 
30 #include "drake/common/cond.h"
33 
34 namespace Eigen {
35 
36 /// Overloads round to mimic std::round from <cmath>.
37 template <typename DerType>
38 double round(const Eigen::AutoDiffScalar<DerType>& x) {
39  using std::round;
40  return round(x.value());
41 }
42 
43 /// Overloads isinf to mimic std::isinf from <cmath>.
44 template <typename DerType>
45 bool isinf(const Eigen::AutoDiffScalar<DerType>& x) {
46  using std::isinf;
47  return isinf(x.value());
48 }
49 
50 /// Overloads isnan to mimic std::isnan from <cmath>.
51 template <typename DerType>
52 bool isnan(const Eigen::AutoDiffScalar<DerType>& x) {
53  using std::isnan;
54  return isnan(x.value());
55 }
56 
57 /// Overloads floor to mimic std::floor from <cmath>.
58 template <typename DerType>
59 double floor(const Eigen::AutoDiffScalar<DerType>& x) {
60  using std::floor;
61  return floor(x.value());
62 }
63 
64 /// Overloads ceil to mimic std::ceil from <cmath>.
65 template <typename DerType>
66 double ceil(const Eigen::AutoDiffScalar<DerType>& x) {
67  using std::ceil;
68  return ceil(x.value());
69 }
70 
71 /// Overloads copysign from <cmath>.
72 template <typename DerType, typename T>
73 Eigen::AutoDiffScalar<DerType> copysign(const Eigen::AutoDiffScalar<DerType>& x,
74  const T& y) {
75  using std::isnan;
76  if (isnan(x)) return (y >= 0) ? NAN : -NAN;
77  if ((x < 0 && y >= 0) || (x >= 0 && y < 0))
78  return -x;
79  else
80  return x;
81 }
82 
83 /// Overloads copysign from <cmath>.
84 template <typename DerType>
85 double copysign(double x, const Eigen::AutoDiffScalar<DerType>& y) {
86  using std::isnan;
87  if (isnan(x)) return (y >= 0) ? NAN : -NAN;
88  if ((x < 0 && y >= 0) || (x >= 0 && y < 0))
89  return -x;
90  else
91  return x;
92 }
93 
94 /// Overloads pow for an AutoDiffScalar base and exponent, implementing the
95 /// chain rule.
96 template <typename DerTypeA, typename DerTypeB>
97 Eigen::AutoDiffScalar<
98  typename internal::remove_all<DerTypeA>::type::PlainObject>
99 pow(const Eigen::AutoDiffScalar<DerTypeA>& base,
100  const Eigen::AutoDiffScalar<DerTypeB>& exponent) {
101  // The two AutoDiffScalars being exponentiated must have the same matrix
102  // type. This includes, but is not limited to, the same scalar type and
103  // the same dimension.
104  static_assert(
105  std::is_same<
106  typename internal::remove_all<DerTypeA>::type::PlainObject,
107  typename internal::remove_all<DerTypeB>::type::PlainObject>::value,
108  "The derivative types must match.");
109 
110  internal::make_coherent(base.derivatives(), exponent.derivatives());
111 
112  const auto& x = base.value();
113  const auto& xgrad = base.derivatives();
114  const auto& y = exponent.value();
115  const auto& ygrad = exponent.derivatives();
116 
117  using std::pow;
118  using std::log;
119  const auto x_to_the_y = pow(x, y);
120  if (ygrad.isZero(std::numeric_limits<double>::epsilon()) ||
121  ygrad.size() == 0) {
122  // The derivative only depends on ∂(x^y)/∂x -- this prevents undefined
123  // behavior in the corner case where ∂(x^y)/∂y is infinite when x = 0,
124  // despite ∂y/∂v being 0.
125  return Eigen::MakeAutoDiffScalar(x_to_the_y, y * pow(x, y - 1) * xgrad);
126  }
127  return Eigen::MakeAutoDiffScalar(
128  // The value is x ^ y.
129  x_to_the_y,
130  // The multivariable chain rule states:
131  // df/dv_i = (∂f/∂x * dx/dv_i) + (∂f/∂y * dy/dv_i)
132  // ∂f/∂x is y*x^(y-1)
133  y * pow(x, y - 1) * xgrad +
134  // ∂f/∂y is (x^y)*ln(x)
135  x_to_the_y * log(x) * ygrad);
136 }
137 
138 } // namespace Eigen
139 
140 namespace drake {
141 
142 /// Returns the autodiff scalar's value() as a double. Never throws.
143 /// Overloads ExtractDoubleOrThrow from common/extract_double.h.
144 template <typename DerType>
145 double ExtractDoubleOrThrow(const Eigen::AutoDiffScalar<DerType>& scalar) {
146  return static_cast<double>(scalar.value());
147 }
148 
149 /// Specializes common/dummy_value.h.
150 template <typename DerType>
151 struct dummy_value<Eigen::AutoDiffScalar<DerType>> {
152  static constexpr Eigen::AutoDiffScalar<DerType> get() {
153  constexpr double kNaN = std::numeric_limits<double>::quiet_NaN();
154  DerType derivatives;
155  derivatives.fill(kNaN);
156  return Eigen::AutoDiffScalar<DerType>(kNaN, derivatives);
157  }
158 };
159 
160 /// Provides if-then-else expression for Eigen::AutoDiffScalar type. To support
161 /// Eigen's generic expressions, we use casting to the plain object after
162 /// applying Eigen::internal::remove_all. It is based on the Eigen's
163 /// implementation of min/max function for AutoDiffScalar type
164 /// (https://bitbucket.org/eigen/eigen/src/10a1de58614569c9250df88bdfc6402024687bc6/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h?at=default&fileviewer=file-view-default#AutoDiffScalar.h-546).
165 template <typename DerType1, typename DerType2>
166 inline Eigen::AutoDiffScalar<
167  typename Eigen::internal::remove_all<DerType1>::type::PlainObject>
168 if_then_else(bool f_cond, const Eigen::AutoDiffScalar<DerType1>& x,
169  const Eigen::AutoDiffScalar<DerType2>& y) {
170  typedef Eigen::AutoDiffScalar<
171  typename Eigen::internal::remove_all<DerType1>::type::PlainObject>
172  ADS1;
173  typedef Eigen::AutoDiffScalar<
174  typename Eigen::internal::remove_all<DerType2>::type::PlainObject>
175  ADS2;
176  static_assert(std::is_same<ADS1, ADS2>::value,
177  "The derivative types must match.");
178  return f_cond ? ADS1(x) : ADS2(y);
179 }
180 
181 /// Provides special case of cond expression for Eigen::AutoDiffScalar type.
182 template <typename DerType, typename... Rest>
183 Eigen::AutoDiffScalar<
184  typename Eigen::internal::remove_all<DerType>::type::PlainObject>
185 cond(bool f_cond, const Eigen::AutoDiffScalar<DerType>& e_then, Rest... rest) {
186  return if_then_else(f_cond, e_then, cond(rest...));
187 }
188 
189 } // namespace drake
bool isnan(const Eigen::AutoDiffScalar< DerType > &x)
Overloads isnan to mimic std::isnan from <cmath>.
Definition: autodiff_overloads.h:52
int y
Definition: rgbd_renderer_test.cc:33
double ceil(const Eigen::AutoDiffScalar< DerType > &x)
Overloads ceil to mimic std::ceil from <cmath>.
Definition: autodiff_overloads.h:66
std::vector< Number > x
Definition: ipopt_solver.cc:150
Definition: automotive_demo.cc:88
Eigen::AutoDiffScalar< typename Eigen::internal::remove_all< DerType1 >::type::PlainObject > if_then_else(bool f_cond, const Eigen::AutoDiffScalar< DerType1 > &x, const Eigen::AutoDiffScalar< DerType2 > &y)
Provides if-then-else expression for Eigen::AutoDiffScalar type.
Definition: autodiff_overloads.h:168
double round(const Eigen::AutoDiffScalar< DerType > &x)
Overloads round to mimic std::round from <cmath>.
Definition: autodiff_overloads.h:38
Definition: autodiff_overloads.h:34
double floor(const Eigen::AutoDiffScalar< DerType > &x)
Overloads floor to mimic std::floor from <cmath>.
Definition: autodiff_overloads.h:59
int value
Definition: copyable_unique_ptr_test.cc:61
Provides Drake&#39;s assertion implementation.
double ExtractDoubleOrThrow(const Eigen::AutoDiffScalar< DerType > &scalar)
Returns the autodiff scalar&#39;s value() as a double.
Definition: autodiff_overloads.h:145
Eigen::AutoDiffScalar< typename Eigen::internal::remove_all< DerType >::type::PlainObject > cond(bool f_cond, const Eigen::AutoDiffScalar< DerType > &e_then, Rest...rest)
Provides special case of cond expression for Eigen::AutoDiffScalar type.
Definition: autodiff_overloads.h:185
Eigen::AutoDiffScalar< DerType > copysign(const Eigen::AutoDiffScalar< DerType > &x, const T &y)
Overloads copysign from <cmath>.
Definition: autodiff_overloads.h:73
Provides a "dummy" value for a ScalarType – a value that is unlikely to be mistaken for a purposeful...
Definition: dummy_value.h:17
bool isinf(const Eigen::AutoDiffScalar< DerType > &x)
Overloads isinf to mimic std::isinf from <cmath>.
Definition: autodiff_overloads.h:45
Polynomial< CoefficientType > pow(const Polynomial< CoefficientType > &base, typename Polynomial< CoefficientType >::PowerType exponent)
Provides power function for Polynomial.
Definition: polynomial.h:449
Eigen::AutoDiffScalar< typename internal::remove_all< DerTypeA >::type::PlainObject > pow(const Eigen::AutoDiffScalar< DerTypeA > &base, const Eigen::AutoDiffScalar< DerTypeB > &exponent)
Overloads pow for an AutoDiffScalar base and exponent, implementing the chain rule.
Definition: autodiff_overloads.h:99
Expression log(const Expression &e)
Definition: symbolic_expression.cc:527