11#ifndef EIGEN_AUTODIFF_SCALAR_H
12#define EIGEN_AUTODIFF_SCALAR_H
15#include "./InternalHeaderCheck.h"
21template <
typename DerivativeType,
bool Enable>
22struct auto_diff_special_op;
24template <
typename DerivativeType,
typename OtherDerivativeType,
typename EnableIf =
void>
25struct maybe_coherent_pad_helper {
26 static constexpr int SizeAtCompileTime =
27 max_size_prefer_dynamic(DerivativeType::SizeAtCompileTime, OtherDerivativeType::SizeAtCompileTime);
28 using type = CoherentPadOp<DerivativeType, SizeAtCompileTime>;
29 static type pad(
const DerivativeType& x,
const OtherDerivativeType& y) {
32 return CoherentPadOp<DerivativeType, SizeAtCompileTime>(x, numext::maxi(x.size(), y.size()));
38template <
typename DerivativeType,
typename OtherDerivativeType>
39struct maybe_coherent_pad_helper<
40 DerivativeType, OtherDerivativeType,
41 std::enable_if_t<enum_ge_not_dynamic(DerivativeType::SizeAtCompileTime, OtherDerivativeType::SizeAtCompileTime)>> {
42 using type =
const DerivativeType&;
43 static const DerivativeType& pad(
const DerivativeType& x,
const OtherDerivativeType& ) {
return x; }
46template <
typename DerivativeType,
typename OtherDerivativeType>
47typename maybe_coherent_pad_helper<DerivativeType, OtherDerivativeType>::type MaybeCoherentPad(
48 const DerivativeType& x,
const OtherDerivativeType& y) {
49 return maybe_coherent_pad_helper<DerivativeType, OtherDerivativeType>::pad(x, y);
52template <
typename Op,
typename LhsDerivativeType,
typename RhsDerivativeType>
53auto MakeCoherentCwiseBinaryOp(
const LhsDerivativeType& x,
const RhsDerivativeType& y, Op op = Op()) {
54 const auto& lhs = MaybeCoherentPad(x, y);
55 const auto& rhs = MaybeCoherentPad(y, x);
56 return CwiseBinaryOp<Op, remove_all_t<
decltype(lhs)>, remove_all_t<
decltype(rhs)>>(lhs, rhs, op);
61template <
typename DerivativeType>
64template <
typename NewDerType>
95template <
typename DerivativeType>
97 :
public internal::auto_diff_special_op<
98 DerivativeType, !std::is_same<typename internal::traits<internal::remove_all_t<DerivativeType>>::Scalar,
99 typename NumTraits<typename internal::traits<
100 internal::remove_all_t<DerivativeType>>::Scalar>::Real>::value> {
102 typedef internal::auto_diff_special_op<
105 typename internal::traits<internal::remove_all_t<DerivativeType>>::Scalar,
108 typedef internal::remove_all_t<DerivativeType> DerType;
109 typedef typename internal::traits<DerType>::Scalar Scalar;
112 using Base::operator+;
113 using Base::operator*;
120 AutoDiffScalar(
const Scalar& value,
int nbDer,
int derNumber) : m_value(value), m_derivatives(DerType::Zero(nbDer)) {
121 m_derivatives.coeffRef(derNumber) = Scalar(1);
127 if (m_derivatives.size() > 0) m_derivatives.setZero();
131 AutoDiffScalar(
const Scalar& value,
const DerType& der) : m_value(value), m_derivatives(der) {}
133#ifndef EIGEN_PARSED_BY_DOXYGEN
134 template <
typename OtherDerType,
136 std::is_same<Scalar, typename internal::traits<internal::remove_all_t<OtherDerType>>::Scalar>::value &&
137 std::is_convertible<OtherDerType, DerType>::value,
140 template <
typename OtherDerType>
143 : m_value(other.value()), m_derivatives(other.derivatives()) {
146#ifndef EIGEN_PARSED_BY_DOXYGEN
147 template <
typename OtherDerType>
148 EIGEN_DEPRECATED_WITH_REASON(
"Omit the implementation-only second argument.")
152 std::is_same<Scalar, typename internal::traits<internal::remove_all_t<OtherDerType>>::Scalar>::value &&
153 std::is_convertible<OtherDerType, DerType>::value,
158 friend std::ostream& operator<<(std::ostream& s,
const AutoDiffScalar& a) {
return s << a.value(); }
162 template <
typename OtherDerType>
164 m_value = other.value();
165 m_derivatives = other.derivatives();
170 m_value = other.value();
171 m_derivatives = other.derivatives();
177 if (m_derivatives.size() > 0) m_derivatives.setZero();
184 inline const Scalar& value()
const {
return m_value; }
185 inline Scalar& value() {
return m_value; }
187 inline const DerType& derivatives()
const {
return m_derivatives; }
188 inline DerType& derivatives() {
return m_derivatives; }
190 inline bool operator<(
const Scalar& other)
const {
return m_value < other; }
191 inline bool operator<=(
const Scalar& other)
const {
return m_value <= other; }
192 inline bool operator>(
const Scalar& other)
const {
return m_value > other; }
193 inline bool operator>=(
const Scalar& other)
const {
return m_value >= other; }
194 inline bool operator==(
const Scalar& other)
const {
return m_value == other; }
195 inline bool operator!=(
const Scalar& other)
const {
return m_value != other; }
197 friend inline bool operator<(
const Scalar& a,
const AutoDiffScalar& b) {
return a < b.value(); }
198 friend inline bool operator<=(
const Scalar& a,
const AutoDiffScalar& b) {
return a <= b.value(); }
199 friend inline bool operator>(
const Scalar& a,
const AutoDiffScalar& b) {
return a > b.value(); }
200 friend inline bool operator>=(
const Scalar& a,
const AutoDiffScalar& b) {
return a >= b.value(); }
201 friend inline bool operator==(
const Scalar& a,
const AutoDiffScalar& b) {
return a == b.value(); }
202 friend inline bool operator!=(
const Scalar& a,
const AutoDiffScalar& b) {
return a != b.value(); }
204 template <
typename OtherDerType>
206 return m_value < b.value();
208 template <
typename OtherDerType>
210 return m_value <= b.value();
212 template <
typename OtherDerType>
214 return m_value > b.value();
216 template <
typename OtherDerType>
218 return m_value >= b.value();
220 template <
typename OtherDerType>
222 return m_value == b.value();
224 template <
typename OtherDerType>
226 return m_value != b.value();
242 template <
typename OtherDerType>
244 return MakeAutoDiffScalar(
245 m_value + other.value(),
246 internal::MakeCoherentCwiseBinaryOp<internal::scalar_sum_op<Scalar>>(m_derivatives, other.derivatives()));
249 template <
typename OtherDerType>
251 (*this) = (*this) + other;
270 template <
typename OtherDerType>
272 return MakeAutoDiffScalar(m_value - other.value(),
273 internal::MakeCoherentCwiseBinaryOp<internal::scalar_difference_op<Scalar>>(
274 m_derivatives, other.derivatives()));
277 template <
typename OtherDerType>
279 *
this = *
this - other;
287 inline auto operator*(
const Scalar& other)
const {
288 return MakeAutoDiffScalar(m_value * other, m_derivatives * other);
291 friend inline auto operator*(
const Scalar& other,
const AutoDiffScalar& a) {
292 return MakeAutoDiffScalar(a.value() * other, a.derivatives() * other);
295 inline auto operator/(
const Scalar& other)
const {
296 return MakeAutoDiffScalar(m_value / other, (m_derivatives * (Scalar(1) / other)));
299 friend inline auto operator/(
const Scalar& other,
const AutoDiffScalar& a) {
300 return MakeAutoDiffScalar(other / a.value(), a.derivatives() * (Scalar(-other) / (a.value() * a.value())));
303 template <
typename OtherDerType>
305 return MakeAutoDiffScalar(m_value / other.value(),
306 internal::MakeCoherentCwiseBinaryOp<internal::scalar_difference_op<Scalar>>(
307 m_derivatives * other.value(), (other.derivatives() * m_value)) *
308 (Scalar(1) / (other.value() * other.value())));
311 template <
typename OtherDerType>
313 return MakeAutoDiffScalar(m_value * other.value(),
314 internal::MakeCoherentCwiseBinaryOp<internal::scalar_sum_op<Scalar>>(
315 m_derivatives * other.value(), other.derivatives() * m_value));
319 *
this = *
this * other;
323 template <
typename OtherDerType>
325 *
this = *
this * other;
330 *
this = *
this / other;
334 template <
typename OtherDerType>
336 *
this = *
this / other;
342 DerType m_derivatives;
347template <
typename DerivativeType>
348struct auto_diff_special_op<DerivativeType, true> {
349 typedef remove_all_t<DerivativeType> DerType;
350 typedef typename traits<DerType>::Scalar Scalar;
351 typedef typename NumTraits<Scalar>::Real Real;
353 const AutoDiffScalar<DerivativeType>& derived()
const {
354 return *
static_cast<const AutoDiffScalar<DerivativeType>*
>(
this);
356 AutoDiffScalar<DerivativeType>& derived() {
return *
static_cast<AutoDiffScalar<DerivativeType>*
>(
this); }
358 inline AutoDiffScalar<DerType&> operator+(
const Real& other)
const {
359 return AutoDiffScalar<DerType&>(derived().value() + other, derived().derivatives());
362 friend inline AutoDiffScalar<DerType&> operator+(
const Real& a,
const AutoDiffScalar<DerivativeType>& b) {
363 return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives());
366 inline AutoDiffScalar<DerivativeType>& operator+=(
const Real& other) {
367 derived().value() += other;
371 inline AutoDiffScalar<typename CwiseUnaryOp<bind2nd_op<scalar_product_op<Scalar, Real>>, DerType>::Type> operator*(
372 const Real& other)
const {
373 return AutoDiffScalar<typename CwiseUnaryOp<bind2nd_op<scalar_product_op<Scalar, Real>>, DerType>::Type>(
374 derived().value() * other, derived().derivatives() * other);
377 friend inline AutoDiffScalar<typename CwiseUnaryOp<bind1st_op<scalar_product_op<Real, Scalar>>, DerType>::Type>
378 operator*(
const Real& other,
const AutoDiffScalar<DerivativeType>& a) {
379 return AutoDiffScalar<typename CwiseUnaryOp<bind1st_op<scalar_product_op<Real, Scalar>>, DerType>::Type>(
380 a.value() * other, a.derivatives() * other);
383 inline AutoDiffScalar<DerivativeType>& operator*=(
const Scalar& other) {
384 *
this = *
this * other;
389template <
typename DerivativeType>
390struct auto_diff_special_op<DerivativeType, false> {
391 void operator*()
const;
392 void operator-()
const;
393 void operator+()
const;
398template <
typename DerType,
typename BinOp>
400 typedef AutoDiffScalar<DerType> ReturnType;
403template <
typename DerType,
typename BinOp>
405 typedef AutoDiffScalar<DerType> ReturnType;
408#define EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(FUNC, CODE) \
409 template <typename DerType> \
410 inline auto FUNC(const Eigen::AutoDiffScalar<DerType>& x) { \
411 using namespace Eigen; \
412 typedef typename Eigen::internal::traits<Eigen::internal::remove_all_t<DerType>>::Scalar Scalar; \
413 EIGEN_UNUSED_VARIABLE(sizeof(Scalar)); \
417template <
typename DerType>
418struct CleanedUpDerType {
419 typedef AutoDiffScalar<typename Eigen::internal::remove_all_t<DerType>::PlainObject> type;
422template <
typename DerType>
426template <
typename DerType>
430template <
typename DerType>
434template <
typename DerType>
436 return (numext::isnan)(x.value());
438template <
typename DerType>
440 return (numext::isinf)(x.value());
442template <
typename DerType>
444 return (numext::isfinite)(x.value());
446template <
typename DerType,
typename T>
448 typedef typename CleanedUpDerType<DerType>::type ADS;
449 return (x <= y ? ADS(x) : ADS(y));
451template <
typename DerType,
typename T>
453 typedef typename CleanedUpDerType<DerType>::type ADS;
454 return (x >= y ? ADS(x) : ADS(y));
456template <
typename DerType,
typename T>
458 typedef typename CleanedUpDerType<DerType>::type ADS;
459 return (x < y ? ADS(x) : ADS(y));
461template <
typename DerType,
typename T>
463 typedef typename CleanedUpDerType<DerType>::type ADS;
464 return (x > y ? ADS(x) : ADS(y));
466template <
typename DerType>
470 return (x.value() <= y.value() ? x : y);
472template <
typename DerType>
475 return (x.value() >= y.value() ? x : y);
478EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs,
using std::abs;
479 return Eigen::MakeAutoDiffScalar(abs(x.value()),
480 x.derivatives() * (x.value() < 0 ? -1 : 1));)
482EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs2,
using numext::abs2;
483 return Eigen::MakeAutoDiffScalar(abs2(x.value()),
484 x.derivatives() * (Scalar(2) * x.value()));)
486EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sqrt,
using std::sqrt; Scalar sqrtx = sqrt(x.value());
487 return Eigen::MakeAutoDiffScalar(sqrtx, x.derivatives() * (Scalar(0.5) / sqrtx));)
489EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(cos,
using std::cos;
using std::sin;
490 return Eigen::MakeAutoDiffScalar(cos(x.value()),
491 x.derivatives() * (-sin(x.value())));)
493EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sin,
using std::sin;
using std::cos;
494 return Eigen::MakeAutoDiffScalar(sin(x.value()), x.derivatives() * cos(x.value()));)
496EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(exp,
using std::exp; Scalar expx = exp(x.value());
497 return Eigen::MakeAutoDiffScalar(expx, x.derivatives() * expx);)
499EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(log,
using std::log;
500 return Eigen::MakeAutoDiffScalar(log(x.value()),
501 x.derivatives() * (Scalar(1) / x.value()));)
503template <typename DerType>
504inline auto pow(
const Eigen::AutoDiffScalar<DerType>& x,
505 const typename internal::traits<internal::remove_all_t<DerType>>::Scalar& y) {
506 using namespace Eigen;
508 return Eigen::MakeAutoDiffScalar(pow(x.value(), y), x.derivatives() * (y * pow(x.value(), y - 1)));
511template <
typename DerTypeA,
typename DerTypeB>
515 typedef typename internal::traits<internal::remove_all_t<DerTypeA>>::Scalar Scalar;
518 ret.value() = atan2(a.value(), b.value());
520 Scalar squared_hypot = a.value() * a.value() + b.value() * b.value();
523 ret.derivatives() = (a.derivatives() * b.value() - a.value() * b.derivatives()) / squared_hypot;
528EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(tan,
using std::tan;
using std::cos;
return Eigen::MakeAutoDiffScalar(
529 tan(x.value()), x.derivatives() * (Scalar(1) / numext::abs2(cos(x.value()))));)
531EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(asin,
using std::sqrt;
using std::asin;
return Eigen::MakeAutoDiffScalar(
533 x.derivatives() * (Scalar(1) / sqrt(1 - numext::abs2(x.value()))));)
535EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(acos,
using std::sqrt;
using std::acos;
return Eigen::MakeAutoDiffScalar(
537 x.derivatives() * (Scalar(-1) / sqrt(1 - numext::abs2(x.value()))));)
539EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
540 tanh,
using std::cosh;
using std::tanh;
541 return Eigen::MakeAutoDiffScalar(tanh(x.value()), x.derivatives() * (Scalar(1) / numext::abs2(cosh(x.value()))));)
543EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sinh,
using std::sinh;
using std::cosh;
544 return Eigen::MakeAutoDiffScalar(sinh(x.value()),
545 x.derivatives() * cosh(x.value()));)
547EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(cosh,
using std::sinh;
using std::cosh;
548 return Eigen::MakeAutoDiffScalar(cosh(x.value()),
549 x.derivatives() * sinh(x.value()));)
551#undef EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY
553template <typename DerType>
556 typedef internal::remove_all_t<DerType> DerTypeCleaned;
558 DerTypeCleaned::RowsAtCompileTime, DerTypeCleaned::ColsAtCompileTime, 0,
559 DerTypeCleaned::MaxRowsAtCompileTime, DerTypeCleaned::MaxColsAtCompileTime>>
564 enum { RequireInitialization = 1 };
568template <
typename DerivativeType>
569struct is_identically_zero_impl<AutoDiffScalar<DerivativeType>> {
570 static inline bool run(
const AutoDiffScalar<DerivativeType>& s) {
571 const DerivativeType& derivatives = s.derivatives();
572 for (
int i = 0; i < derivatives.size(); ++i) {
573 if (!numext::is_exactly_zero(derivatives[i])) {
577 return numext::is_exactly_zero(s.value());
586class numeric_limits<Eigen::AutoDiffScalar<T>> :
public numeric_limits<typename T::Scalar> {};
589class numeric_limits<Eigen::AutoDiffScalar<T&>> :
public numeric_limits<typename T::Scalar> {};
A scalar type replacement with automatic differentiation capability.
Definition AutoDiffScalar.h:100
AutoDiffScalar()
Definition AutoDiffScalar.h:116
AutoDiffScalar(const Scalar &value, int nbDer, int derNumber)
Definition AutoDiffScalar.h:120
AutoDiffScalar(const Real &value)
Definition AutoDiffScalar.h:126
AutoDiffScalar(const Scalar &value, const DerType &der)
Definition AutoDiffScalar.h:131
Namespace containing all symbols from the Eigen library.