diff options
Diffstat (limited to 'unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h')
-rw-r--r-- | unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h b/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h new file mode 100644 index 000000000..852b43bf5 --- /dev/null +++ b/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h @@ -0,0 +1,321 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. Eigen itself is part of the KDE project. +// +// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#ifndef EIGEN_AUTODIFF_SCALAR_H +#define EIGEN_AUTODIFF_SCALAR_H + +namespace Eigen { + +/** \class AutoDiffScalar + * \brief A scalar type replacement with automatic differentation capability + * + * \param DerType the vector type used to store/represent the derivatives (e.g. Vector3f) + * + * This class represents a scalar value while tracking its respective derivatives. + * + * It supports the following list of global math function: + * - std::abs, std::sqrt, std::pow, std::exp, std::log, std::sin, std::cos, + * - ei_abs, ei_sqrt, ei_pow, ei_exp, ei_log, ei_sin, ei_cos, + * - ei_conj, ei_real, ei_imag, ei_abs2. + * + * AutoDiffScalar can be used as the scalar type of an Eigen::Matrix object. However, + * in that case, the expression template mechanism only occurs at the top Matrix level, + * while derivatives are computed right away. + * + */ +template<typename DerType> +class AutoDiffScalar +{ + public: + typedef typename ei_traits<DerType>::Scalar Scalar; + + inline AutoDiffScalar() {} + + inline AutoDiffScalar(const Scalar& value) + : m_value(value) + { + if(m_derivatives.size()>0) + m_derivatives.setZero(); + } + + inline AutoDiffScalar(const Scalar& value, const DerType& der) + : m_value(value), m_derivatives(der) + {} + + template<typename OtherDerType> + inline AutoDiffScalar(const AutoDiffScalar<OtherDerType>& other) + : m_value(other.value()), m_derivatives(other.derivatives()) + {} + + inline AutoDiffScalar(const AutoDiffScalar& other) + : m_value(other.value()), m_derivatives(other.derivatives()) + {} + + template<typename OtherDerType> + inline AutoDiffScalar& operator=(const AutoDiffScalar<OtherDerType>& other) + { + m_value = other.value(); + m_derivatives = other.derivatives(); + return *this; + } + + inline AutoDiffScalar& operator=(const AutoDiffScalar& other) + { + m_value = other.value(); + m_derivatives = other.derivatives(); + return *this; + } + +// inline operator const Scalar& () const { return m_value; } +// inline operator Scalar& () { return m_value; } + + inline const Scalar& value() const { return m_value; } + inline Scalar& value() { return m_value; } + + inline const DerType& derivatives() const { return m_derivatives; } + inline DerType& derivatives() { return m_derivatives; } + + template<typename OtherDerType> + inline const AutoDiffScalar<CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerType,OtherDerType> > + operator+(const AutoDiffScalar<OtherDerType>& other) const + { + return AutoDiffScalar<CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerType,OtherDerType> >( + m_value + other.value(), + m_derivatives + other.derivatives()); + } + + template<typename OtherDerType> + inline AutoDiffScalar& + operator+=(const AutoDiffScalar<OtherDerType>& other) + { + (*this) = (*this) + other; + return *this; + } + + template<typename OtherDerType> + inline const AutoDiffScalar<CwiseBinaryOp<ei_scalar_difference_op<Scalar>, DerType,OtherDerType> > + operator-(const AutoDiffScalar<OtherDerType>& other) const + { + return AutoDiffScalar<CwiseBinaryOp<ei_scalar_difference_op<Scalar>, DerType,OtherDerType> >( + m_value - other.value(), + m_derivatives - other.derivatives()); + } + + template<typename OtherDerType> + inline AutoDiffScalar& + operator-=(const AutoDiffScalar<OtherDerType>& other) + { + *this = *this - other; + return *this; + } + + template<typename OtherDerType> + inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_opposite_op<Scalar>, DerType> > + operator-() const + { + return AutoDiffScalar<CwiseUnaryOp<ei_scalar_opposite_op<Scalar>, DerType> >( + -m_value, + -m_derivatives); + } + + inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> > + operator*(const Scalar& other) const + { + return AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >( + m_value * other, + (m_derivatives * other)); + } + + friend inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> > + operator*(const Scalar& other, const AutoDiffScalar& a) + { + return AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >( + a.value() * other, + a.derivatives() * other); + } + + inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> > + operator/(const Scalar& other) const + { + return AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >( + m_value / other, + (m_derivatives * (Scalar(1)/other))); + } + + friend inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> > + operator/(const Scalar& other, const AutoDiffScalar& a) + { + return AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >( + other / a.value(), + a.derivatives() * (-Scalar(1)/other)); + } + + template<typename OtherDerType> + inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, + NestByValue<CwiseBinaryOp<ei_scalar_difference_op<Scalar>, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, OtherDerType> > > > > > + operator/(const AutoDiffScalar<OtherDerType>& other) const + { + return AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, + NestByValue<CwiseBinaryOp<ei_scalar_difference_op<Scalar>, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, OtherDerType> > > > > >( + m_value / other.value(), + ((m_derivatives * other.value()).nestByValue() - (m_value * other.derivatives()).nestByValue()).nestByValue() + * (Scalar(1)/(other.value()*other.value()))); + } + + template<typename OtherDerType> + inline const AutoDiffScalar<CwiseBinaryOp<ei_scalar_sum_op<Scalar>, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, OtherDerType> > > > + operator*(const AutoDiffScalar<OtherDerType>& other) const + { + return AutoDiffScalar<CwiseBinaryOp<ei_scalar_sum_op<Scalar>, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >, + NestByValue<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, OtherDerType> > > >( + m_value * other.value(), + (m_derivatives * other.value()).nestByValue() + (m_value * other.derivatives()).nestByValue()); + } + + inline AutoDiffScalar& operator*=(const Scalar& other) + { + *this = *this * other; + return *this; + } + + template<typename OtherDerType> + inline AutoDiffScalar& operator*=(const AutoDiffScalar<OtherDerType>& other) + { + *this = *this * other; + return *this; + } + + protected: + Scalar m_value; + DerType m_derivatives; + +}; + +} + +#define EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(FUNC,CODE) \ + template<typename DerType> \ + inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<DerType>::Scalar>, DerType> > \ + FUNC(const AutoDiffScalar<DerType>& x) { \ + typedef typename ei_traits<DerType>::Scalar Scalar; \ + typedef AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> > ReturnType; \ + CODE; \ + } + +namespace std +{ + EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs, + return ReturnType(std::abs(x.value()), x.derivatives() * (sign(x.value())));) + + EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sqrt, + Scalar sqrtx = std::sqrt(x.value()); + return ReturnType(sqrtx,x.derivatives() * (Scalar(0.5) / sqrtx));) + + EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(cos, + return ReturnType(std::cos(x.value()), x.derivatives() * (-std::sin(x.value())));) + + EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sin, + return ReturnType(std::sin(x.value()),x.derivatives() * std::cos(x.value()));) + + EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(exp, + Scalar expx = std::exp(x.value()); + return ReturnType(expx,x.derivatives() * expx);) + + EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_log, + return ReturnType(std::log(x.value),x.derivatives() * (Scalar(1).x.value()));) + + template<typename DerType> + inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<DerType>::Scalar>, DerType> > + pow(const AutoDiffScalar<DerType>& x, typename ei_traits<DerType>::Scalar y) + { + typedef typename ei_traits<DerType>::Scalar Scalar; + return AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<Scalar>, DerType> >( + std::pow(x.value(),y), + x.derivatives() * (y * std::pow(x.value(),y-1))); + } + +} + +namespace Eigen { + +template<typename DerType> +inline const AutoDiffScalar<DerType>& ei_conj(const AutoDiffScalar<DerType>& x) { return x; } +template<typename DerType> +inline const AutoDiffScalar<DerType>& ei_real(const AutoDiffScalar<DerType>& x) { return x; } +template<typename DerType> +inline typename DerType::Scalar ei_imag(const AutoDiffScalar<DerType>&) { return 0.; } + +EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_abs, + return ReturnType(ei_abs(x.value()), x.derivatives() * (sign(x.value())));) + +EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_abs2, + return ReturnType(ei_abs2(x.value()), x.derivatives() * (Scalar(2)*x.value()));) + +EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_sqrt, + Scalar sqrtx = ei_sqrt(x.value()); + return ReturnType(sqrtx,x.derivatives() * (Scalar(0.5) / sqrtx));) + +EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_cos, + return ReturnType(ei_cos(x.value()), x.derivatives() * (-ei_sin(x.value())));) + +EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_sin, + return ReturnType(ei_sin(x.value()),x.derivatives() * ei_cos(x.value()));) + +EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_exp, + Scalar expx = ei_exp(x.value()); + return ReturnType(expx,x.derivatives() * expx);) + +EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_log, + return ReturnType(ei_log(x.value),x.derivatives() * (Scalar(1).x.value()));) + +template<typename DerType> +inline const AutoDiffScalar<CwiseUnaryOp<ei_scalar_multiple_op<typename ei_traits<DerType>::Scalar>, DerType> > +ei_pow(const AutoDiffScalar<DerType>& x, typename ei_traits<DerType>::Scalar y) +{ return std::pow(x,y);} + +#undef EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY + +template<typename DerType> struct NumTraits<AutoDiffScalar<DerType> > +{ + typedef typename DerType::Scalar Real; + typedef AutoDiffScalar<DerType> FloatingPoint; + enum { + IsComplex = 0, + HasFloatingPoint = 1, + ReadCost = 1, + AddCost = 1, + MulCost = 1 + }; +}; + +} + +#endif // EIGEN_AUTODIFF_SCALAR_H |