New user self-registration is currently disabled. Please email eigen-core-team @ lists.tuxfamily.org if you need an account.
Bug 1223 - AutoDiffScalar mixed-type min/max doesn't work with expressions
AutoDiffScalar mixed-type min/max doesn't work with expressions
Status: RESOLVED FIXED
Product: Eigen
Classification: Unclassified
Component: Unsupported modules
3.3 (current stable)
All All
: Normal Unknown
Assigned To: Nobody
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2016-05-10 12:31 UTC by Daniel Vollmer
Modified: 2016-07-25 13:06 UTC (History)
2 users (show)



Attachments

Description Daniel Vollmer 2016-05-10 12:31:59 UTC
The following example fails to compile as soon as the argument to min/max is an expression, because the return-type of ADS<DerType&> of min/max is being initialized with only the scalar value, not setting up the m_derivatives *reference*, I think.

This is similar-isa to bug #1222.


#include <algorithm>

#include "Eigen/Core"
#include "unsupported/Eigen/AutoDiff"

int main (int argc, char const *argv[])
{
  using std::min;
  typedef Eigen::AutoDiffScalar<Eigen::Vector3d> AD;
  
  const double _cv1_3 = 1.0;
  const AD chi_3 = 1.0;
  const AD denom = 1.0;
  
  // fails because implementation of min attempts to construct ADS<DerType&> via constructor AutoDiffScalar(const Real& value) without initializing m_derivatives (which is a reference in this case)
  const AD t = min(denom / chi_3, 1.0);
  
  // const AD t2 = min(denom / (chi_3 * _cv1_3), 1.0);

  return 0;
}
Comment 1 Daniel Vollmer 2016-05-10 15:07:49 UTC
Changing the ADS implementation of mixed argument min/max as follows seems to at least make the code compile...

I attempted to not return an expression but just a matching new instance of the "plain" AutoDiffScalar. I couldn't get this to work as an CwiseBinaryOp<scalar_min/max_op> expression...

--- a/AutoDiffScalar.h	2016-05-10 04:24:55.000000000 +0200
+++ b/AutoDiffScalar.h	2016-05-10 16:47:36.000000000 +0200
@@ -547,14 +547,30 @@
 inline const AutoDiffScalar<DerType>& real(const AutoDiffScalar<DerType>& x)  { return x; }
 template<typename DerType>
 inline typename DerType::Scalar imag(const AutoDiffScalar<DerType>&)    { return 0.; }
-template<typename DerType, typename T>
-inline AutoDiffScalar<DerType> (min)(const AutoDiffScalar<DerType>& x, const T& y)    { return (x <= y ? x : y); }
-template<typename DerType, typename T>
-inline AutoDiffScalar<DerType> (max)(const AutoDiffScalar<DerType>& x, const T& y)    { return (x >= y ? x : y); }
-template<typename DerType, typename T>
-inline AutoDiffScalar<DerType> (min)(const T& x, const AutoDiffScalar<DerType>& y)    { return (x < y ? x : y); }
-template<typename DerType, typename T>
-inline AutoDiffScalar<DerType> (max)(const T& x, const AutoDiffScalar<DerType>& y)    { return (x > y ? x : y); }
+template<typename DerType>
+inline Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (min)(const AutoDiffScalar<DerType>& x, const typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar& y)
+{
+  typedef Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ReturnType;
+  return (x.value() <= y ? ReturnType(x.value(), x.derivatives()) : ReturnType(y));
+}
+template<typename DerType>
+inline Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (max)(const AutoDiffScalar<DerType>& x, const typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar& y)
+{
+  typedef Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ReturnType;
+  return (x.value() >= y ? ReturnType(x.value(), x.derivatives()) : ReturnType(y));
+}
+template<typename DerType>
+inline Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (min)(const typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar& x, const AutoDiffScalar<DerType>& y)
+{
+  typedef Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ReturnType;
+  return (x < y.value() ? ReturnType(x) : ReturnType(y.value(), y.derivatives()));
+}
+template<typename DerType>
+inline Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (max)(const typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar& x, const AutoDiffScalar<DerType>& y)
+{
+  typedef Eigen::AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ReturnType;
+  return (x > y.value() ? ReturnType(x) : ReturnType(y.value(), y.derivatives()));
+}
 
 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs,
   using std::abs;




It might also be a good idea to also change the argument type from a value to a const ref for pow's 2nd argument so that alignment is never an issue.


@@ -590,7 +606,7 @@
 
 template<typename DerType>
 inline const Eigen::AutoDiffScalar<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<typename internal::traits<typename internal::remove_all<DerType>::type>::Scalar>, const typename internal::remove_all<DerType>::type> >
-pow(const Eigen::AutoDiffScalar<DerType>& x, typename internal::traits<typename internal::remove_all<DerType>::type>::Scalar y)
+pow(const Eigen::AutoDiffScalar<DerType>& x, const typename internal::traits<typename internal::remove_all<DerType>::type>::Scalar &y)
 {
   using namespace Eigen;
   typedef typename internal::remove_all<DerType>::type DerTypeCleaned;
Comment 2 Gael Guennebaud 2016-05-18 14:29:50 UTC
Thanks for the fixes, slightly adapted:

https://bitbucket.org/eigen/eigen/commits/3fe41bbc3008 (min/max)
https://bitbucket.org/eigen/eigen/commits/6b0546f4716f (pow)
Comment 3 Daniel Vollmer 2016-07-25 12:41:49 UTC
Just as a note: These changes were not back-ported to 3.2 (and I intend to wait for the next beta / RC of 3.3 before testing our code with 3.3, as quite a few things seem to no longer work — but I'm not sure whether the problem is using an in-development snapshot of 3.3, AutoDiffScalar, or me using them incorrectly ;)).
Comment 4 Gael Guennebaud 2016-07-25 13:06:52 UTC
This would be too painful, but next 3.3 beta/RC is coming soon.

Note You need to log in before you can comment on or make changes to this bug.