This bugzilla service is closed. All entries have been migrated to https://gitlab.com/libeigen/eigen
Bug 1223 - AutoDiffScalar mixed-type min/max doesn't work with expressions
Summary: AutoDiffScalar mixed-type min/max doesn't work with expressions
Status: RESOLVED FIXED
Alias: None
Product: Eigen
Classification: Unclassified
Component: Unsupported modules (show other bugs)
Version: 3.3 (current stable)
Hardware: All All
: Normal Unknown
Assignee: Nobody
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-10 12:31 UTC by Daniel Vollmer
Modified: 2019-12-04 15:48 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.
Comment 5 Nobody 2019-12-04 15:48:18 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to gitlab.com's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.com/libeigen/eigen/issues/1223.

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