coin-or / CppAD

A C++ Algorithmic Differentiation Package: Home Page
https://cppad.readthedocs.io
Other
446 stars 94 forks source link

Eigen::NumTraits does not define infinity() or quiet_NaN() #139

Closed benmwebb closed 2 years ago

benmwebb commented 2 years ago

Trying to build this simple (and contrived) test program with latest CppAD and Eigen 3.4.0 (e.g. as packaged in Fedora 36) fails (it worked in Fedora 35, which ships Eigen 3.3.9):

#include <Eigen/Eigenvalues>
#include <Eigen/Core>
#include <cppad/cppad.hpp>
#include <cppad/example/cppad_eigen.hpp>

typedef CppAD::AD<double> ADFloat;
typedef Eigen::Matrix<ADFloat, Eigen::Dynamic, Eigen::Dynamic> ADMatrix;
typedef Eigen::SelfAdjointEigenSolver<ADMatrix::PlainObject> EigenSolver;

int main() {
  ADMatrix x(3, 3);
  EigenSolver solver;
  solver.compute(x);
  return 0;
}

Compilation fails with

/usr/include/eigen3/Eigen/src/Core/MathFunctionsImpl.h:84:43: error: ‘infinity’ is not a member of ‘Eigen::NumTraits<CppAD::A
D<double> >’
   84 |     return NumTraits<RealScalar>::infinity();
      |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
/usr/include/eigen3/Eigen/src/Core/MathFunctionsImpl.h:86:44: error: ‘quiet_NaN’ is not a member of ‘Eigen::NumTraits<CppAD::
AD<double> >’
   86 |     return NumTraits<RealScalar>::quiet_NaN();
      |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~

This appears to be because

  1. Eigen now tries to use NumTraits<RealScalar>::infinity() and NumTraits<RealScalar>::quiet_NaN() in the positive_real_hypot() function in Eigen/src/Core/MathFunctionsImpl.h as of commit bde674164.
  2. CppAD's implementation of Eigen::NumTraits in cppad/example/cppad_eigen.hpp does not define infinity() or quiet_NaN().
benmwebb commented 2 years ago

The new relevant code in Eigen is

  // IEEE IEC 6059 special cases.
  if ((numext::isinf)(x) || (numext::isinf)(y))
    return NumTraits<RealScalar>::infinity();
  if ((numext::isnan)(x) || (numext::isnan)(y))
    return NumTraits<RealScalar>::quiet_NaN();

So CppAD would also need an overload for isinf(const CppAD::AD<RealScalar>&) and isnan(const CppAD::AD<RealScalar>&) in order to compile. I'll see if I can concoct a PR.

bradbell commented 2 years ago

@benmwebb I am busy with other things right now. Perhaps you would like to clone the current master and make a try at what you want here.

I think this is going to require additions to the following file: https://github.com/coin-or/CppAD/blob/master/include/cppad/example/cppad_eigen.hpp

The easiest cases to do in general are probably those that are already in the CppAD::numeric_limits; see https://coin-or.github.io/CppAD/doc/numeric_limits.htm.

To extend this to any base type one would have to add to the base type requirements; see https://coin-or.github.io/CppAD/doc/base_limits.htm

benmwebb commented 2 years ago

@bradbell OK, I made a PR which fixes this issue for me, and did my best to add suitable test cases; all tests pass on my machine.