diff --git a/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h b/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h index 795dd6b4d..ec25106f5 100644 --- a/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h +++ b/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h @@ -64,32 +64,63 @@ void ei_make_coherent(const A& a, const B&b) * while derivatives are computed right away. * */ + +template struct ei_auto_diff_special_op; + + template class AutoDiffScalar + : public ei_auto_diff_special_op + <_DerType, !ei_is_same_type::type>::Scalar, + typename NumTraits::type>::Scalar>::Real>::ret> { public: + typedef ei_auto_diff_special_op + <_DerType, !ei_is_same_type::type>::Scalar, + typename NumTraits::type>::Scalar>::Real>::ret> Base; typedef typename ei_cleantype<_DerType>::type DerType; typedef typename ei_traits::Scalar Scalar; + typedef typename NumTraits::Real Real; - inline AutoDiffScalar() {} + using Base::operator+; + using Base::operator*; - inline AutoDiffScalar(const Scalar& value) + /** Default constructor without any initialization. */ + AutoDiffScalar() {} + + /** Constructs an active scalar from its \a value, + and initializes the \a nbDer derivatives such that it corresponds to the \a derNumber -th variable */ + AutoDiffScalar(const Scalar& value, int nbDer, int derNumber) + : m_value(value), m_derivatives(DerType::Zero(nbDer)) + { + m_derivatives.coeffRef(derNumber) = Scalar(1); + } + + /** Conversion from a scalar constant to an active scalar. + * The derivatives are set to zero. */ + explicit AutoDiffScalar(const Real& value) : m_value(value) { if(m_derivatives.size()>0) m_derivatives.setZero(); } - inline AutoDiffScalar(const Scalar& value, const DerType& der) + /** Constructs an active scalar from its \a value and derivatives \a der */ + AutoDiffScalar(const Scalar& value, const DerType& der) : m_value(value), m_derivatives(der) {} template - inline AutoDiffScalar(const AutoDiffScalar& other) + AutoDiffScalar(const AutoDiffScalar& other) : m_value(other.value()), m_derivatives(other.derivatives()) {} - inline AutoDiffScalar(const AutoDiffScalar& other) + friend std::ostream & operator << (std::ostream & s, const AutoDiffScalar& a) + { + return s << a.value(); + } + + AutoDiffScalar(const AutoDiffScalar& other) : m_value(other.value()), m_derivatives(other.derivatives()) {} @@ -119,14 +150,24 @@ class AutoDiffScalar inline const AutoDiffScalar operator+(const Scalar& other) const { - return AutoDiffScalar(m_value + other, m_derivatives); + return AutoDiffScalar(m_value + other, m_derivatives); } friend inline const AutoDiffScalar operator+(const Scalar& a, const AutoDiffScalar& b) { - return AutoDiffScalar(a + b.value(), b.derivatives()); + return AutoDiffScalar(a + b.value(), b.derivatives()); } +// inline const AutoDiffScalar operator+(const Real& other) const +// { +// return AutoDiffScalar(m_value + other, m_derivatives); +// } + +// friend inline const AutoDiffScalar operator+(const Real& a, const AutoDiffScalar& b) +// { +// return AutoDiffScalar(a + b.value(), b.derivatives()); +// } + inline AutoDiffScalar& operator+=(const Scalar& other) { value() += other; @@ -134,11 +175,11 @@ class AutoDiffScalar } template - inline const AutoDiffScalar,DerType,typename ei_cleantype::type>::Type > + inline const AutoDiffScalar,DerType,typename ei_cleantype::type> > operator+(const AutoDiffScalar& other) const { ei_make_coherent(m_derivatives, other.derivatives()); - return AutoDiffScalar,DerType,typename ei_cleantype::type>::Type >( + return AutoDiffScalar,DerType,typename ei_cleantype::type> >( m_value + other.value(), m_derivatives + other.derivatives()); } @@ -152,11 +193,11 @@ class AutoDiffScalar } template - inline const AutoDiffScalar, DerType,typename ei_cleantype::type>::Type > + inline const AutoDiffScalar, DerType,typename ei_cleantype::type> > operator-(const AutoDiffScalar& other) const { ei_make_coherent(m_derivatives, other.derivatives()); - return AutoDiffScalar, DerType,typename ei_cleantype::type>::Type >( + return AutoDiffScalar, DerType,typename ei_cleantype::type> >( m_value - other.value(), m_derivatives - other.derivatives()); } @@ -170,73 +211,105 @@ class AutoDiffScalar } template - inline const AutoDiffScalar, DerType>::Type > + inline const AutoDiffScalar, DerType> > operator-() const { - return AutoDiffScalar, DerType>::Type >( + return AutoDiffScalar, DerType> >( -m_value, -m_derivatives); } - inline const AutoDiffScalar, DerType>::Type > + inline const AutoDiffScalar, DerType> > operator*(const Scalar& other) const { - return AutoDiffScalar, DerType>::Type >( + return AutoDiffScalar, DerType> >( m_value * other, (m_derivatives * other)); } - friend inline const AutoDiffScalar, DerType>::Type > + friend inline const AutoDiffScalar, DerType> > operator*(const Scalar& other, const AutoDiffScalar& a) { - return AutoDiffScalar, DerType>::Type >( + return AutoDiffScalar, DerType> >( a.value() * other, a.derivatives() * other); } - inline const AutoDiffScalar, DerType>::Type > +// inline const AutoDiffScalar, DerType>::Type > +// operator*(const Real& other) const +// { +// return AutoDiffScalar, DerType>::Type >( +// m_value * other, +// (m_derivatives * other)); +// } +// +// friend inline const AutoDiffScalar, DerType>::Type > +// operator*(const Real& other, const AutoDiffScalar& a) +// { +// return AutoDiffScalar, DerType>::Type >( +// a.value() * other, +// a.derivatives() * other); +// } + + inline const AutoDiffScalar, DerType> > operator/(const Scalar& other) const { - return AutoDiffScalar, DerType>::Type >( + return AutoDiffScalar, DerType> >( m_value / other, (m_derivatives * (Scalar(1)/other))); } - friend inline const AutoDiffScalar, DerType>::Type > + friend inline const AutoDiffScalar, DerType> > operator/(const Scalar& other, const AutoDiffScalar& a) { - return AutoDiffScalar, DerType>::Type >( + return AutoDiffScalar, DerType> >( other / a.value(), a.derivatives() * (-Scalar(1)/other)); } +// inline const AutoDiffScalar, DerType>::Type > +// operator/(const Real& other) const +// { +// return AutoDiffScalar, DerType>::Type >( +// m_value / other, +// (m_derivatives * (Real(1)/other))); +// } +// +// friend inline const AutoDiffScalar, DerType>::Type > +// operator/(const Real& other, const AutoDiffScalar& a) +// { +// return AutoDiffScalar, DerType>::Type >( +// other / a.value(), +// a.derivatives() * (-Real(1)/other)); +// } + template - inline const AutoDiffScalar, - typename MakeCwiseBinaryOp, - typename MakeCwiseUnaryOp, DerType>::Type, - typename MakeCwiseUnaryOp, typename ei_cleantype::type>::Type>::Type >::Type > + inline const AutoDiffScalar, + CwiseBinaryOp, + CwiseUnaryOp, DerType>, + CwiseUnaryOp, typename ei_cleantype::type > > > > operator/(const AutoDiffScalar& other) const { ei_make_coherent(m_derivatives, other.derivatives()); - return AutoDiffScalar, - typename MakeCwiseBinaryOp, - typename MakeCwiseUnaryOp, DerType>::Type, - typename MakeCwiseUnaryOp, typename ei_cleantype::type>::Type>::Type >::Type >( + return AutoDiffScalar, + CwiseBinaryOp, + CwiseUnaryOp, DerType>, + CwiseUnaryOp, typename ei_cleantype::type > > > >( m_value / other.value(), ((m_derivatives * other.value()) - (m_value * other.derivatives())) * (Scalar(1)/(other.value()*other.value()))); } template - inline const AutoDiffScalar, - typename MakeCwiseUnaryOp, DerType>::Type, - typename MakeCwiseUnaryOp, typename ei_cleantype::type>::Type>::Type > + inline const AutoDiffScalar, + CwiseUnaryOp, DerType>, + CwiseUnaryOp, typename ei_cleantype::type> > > operator*(const AutoDiffScalar& other) const { ei_make_coherent(m_derivatives, other.derivatives()); - return AutoDiffScalar, - typename MakeCwiseUnaryOp, DerType>::Type, - typename MakeCwiseUnaryOp, typename ei_cleantype::type>::Type>::Type >( + return AutoDiffScalar, + CwiseUnaryOp, DerType>, + CwiseUnaryOp, typename ei_cleantype::type > > >( m_value * other.value(), (m_derivatives * other.value()) + (m_value * other.derivatives())); } @@ -260,6 +333,78 @@ class AutoDiffScalar }; + +template +struct ei_auto_diff_special_op<_DerType, true> +// : ei_auto_diff_scalar_op<_DerType, typename NumTraits::Real, +// ei_is_same_type::Real>::ret> +{ + typedef typename ei_cleantype<_DerType>::type DerType; + typedef typename ei_traits::Scalar Scalar; + typedef typename NumTraits::Real Real; + +// typedef ei_auto_diff_scalar_op<_DerType, typename NumTraits::Real, +// ei_is_same_type::Real>::ret> Base; + +// using Base::operator+; +// using Base::operator+=; +// using Base::operator-; +// using Base::operator-=; +// using Base::operator*; +// using Base::operator*=; + + const AutoDiffScalar<_DerType>& derived() const { return *static_cast*>(this); } + AutoDiffScalar<_DerType>& derived() { return *static_cast*>(this); } + + + inline const AutoDiffScalar operator+(const Real& other) const + { + return AutoDiffScalar(derived().value() + other, derived().derivatives()); + } + + friend inline const AutoDiffScalar operator+(const Real& a, const AutoDiffScalar<_DerType>& b) + { + return AutoDiffScalar(a + b.value(), b.derivatives()); + } + + inline AutoDiffScalar<_DerType>& operator+=(const Real& other) + { + derived().value() += other; + return derived(); + } + + + inline const AutoDiffScalar, DerType>::Type > + operator*(const Real& other) const + { + return AutoDiffScalar, DerType>::Type >( + derived().value() * other, + derived().derivatives() * other); + } + + friend inline const AutoDiffScalar, DerType>::Type > + operator*(const Real& other, const AutoDiffScalar<_DerType>& a) + { + return AutoDiffScalar, DerType>::Type >( + a.value() * other, + a.derivatives() * other); + } + + inline AutoDiffScalar<_DerType>& operator*=(const Scalar& other) + { + *this = *this * other; + return derived(); + } +}; + +template +struct ei_auto_diff_special_op<_DerType, false> +{ + void operator*() const; + void operator-() const; + void operator+() const; +}; + template struct ei_make_coherent_impl, B> { typedef Matrix A; @@ -304,15 +449,31 @@ struct ei_make_coherent_impl struct ei_scalar_product_traits,A_Scalar> +{ + typedef Matrix ReturnType; +}; + +template struct ei_scalar_product_traits > +{ + typedef Matrix ReturnType; +}; + +template +struct ei_scalar_product_traits,T> +{ + typedef AutoDiffScalar ReturnType; +}; + } #define EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(FUNC,CODE) \ template \ - inline const Eigen::AutoDiffScalar::Scalar>, DerType>::Type > \ + inline const Eigen::AutoDiffScalar::type>::Scalar>, typename Eigen::ei_cleantype::type> > \ FUNC(const Eigen::AutoDiffScalar& x) { \ using namespace Eigen; \ - typedef typename ei_traits::Scalar Scalar; \ - typedef AutoDiffScalar, DerType>::Type > ReturnType; \ + typedef typename ei_traits::type>::Scalar Scalar; \ + typedef AutoDiffScalar, typename ei_cleantype::type> > ReturnType; \ CODE; \ } @@ -335,16 +496,16 @@ namespace std 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()));) + EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(log, + return ReturnType(std::log(x.value()),x.derivatives() * (Scalar(1)/x.value()));) template - inline const Eigen::AutoDiffScalar::Scalar>, DerType>::Type > + inline const Eigen::AutoDiffScalar::Scalar>, DerType> > pow(const Eigen::AutoDiffScalar& x, typename Eigen::ei_traits::Scalar y) { using namespace Eigen; typedef typename ei_traits::Scalar Scalar; - return AutoDiffScalar, DerType>::Type >( + return AutoDiffScalar, DerType> >( std::pow(x.value(),y), x.derivatives() * (y * std::pow(x.value(),y-1))); } @@ -381,10 +542,10 @@ EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(ei_exp, 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()));) + return ReturnType(ei_log(x.value()),x.derivatives() * (Scalar(1)/x.value()));) template -inline const AutoDiffScalar::Scalar>, DerType>::Type > +inline const AutoDiffScalar::Scalar>, DerType> > ei_pow(const AutoDiffScalar& x, typename ei_traits::Scalar y) { return std::pow(x,y);} @@ -392,8 +553,9 @@ ei_pow(const AutoDiffScalar& x, typename ei_traits::Scalar y) template struct NumTraits > { - typedef typename DerType::Scalar Real; + typedef typename NumTraits::Real Real; typedef AutoDiffScalar FloatingPoint; + typedef AutoDiffScalar& Nested; enum { IsComplex = 0, HasFloatingPoint = 1, diff --git a/unsupported/test/autodiff.cpp b/unsupported/test/autodiff.cpp index cac08cd4b..a32d85829 100644 --- a/unsupported/test/autodiff.cpp +++ b/unsupported/test/autodiff.cpp @@ -31,7 +31,7 @@ EIGEN_DONT_INLINE Scalar foo(const Scalar& x, const Scalar& y) // return x+std::sin(y); EIGEN_ASM_COMMENT("mybegin"); return static_cast(x*2 - std::pow(x,2) + 2*std::sqrt(y*y) - 4 * std::sin(x) + 2 * std::cos(y) - std::exp(-0.5*x*x)); -// return x - y;//x*2 -std::pow(x,2);//(2*y/x);// - y*2; + //return x+2*y*x;//x*2 -std::pow(x,2);//(2*y/x);// - y*2; EIGEN_ASM_COMMENT("myend"); }