Skip to content

Method unaryExpr() does not support function pointers in Eigen 3.4rc1

Summary

MatrixBase's method unaryExpr() does not support function pointers in Eigen 3.4rc1, while this works well in Eigen 3.3.

The change of behavior was introduced in commit 11f55b29. As a consequence, unaryExpr() does not support function pointers in Eigen 3.4rc1, branch 3.4, and master. I am not sure if the support for function pointers was dropped for performance reasons. The quick reference guide states

It is also very simple to apply any user defined function foo using DenseBase::unaryExpr together with std::ptr_fun (c++03), std::ref (c++11), or lambdas (c++11):

mat1.unaryExpr(std::ptr_fun(foo));
mat1.unaryExpr(std::ref(foo));
mat1.unaryExpr([](double x) { return foo(x); });

All these three methods work well in all versions of Eigen I have tested, so these can be used as alternatives.

Nevertheless, I could not find any information on this in the release notes for Eigen 3.4.

Let me therefore propose to add support for function pointers again and add a regression test. If this is not intended we should add a note to section Changes that might impact existing code in the release notes.

Environment

  • Operating System : Linux
  • Architecture : x64
  • Eigen Version : 3.4rc1
  • Compiler Version : Gcc8.3
  • Compile Flags : none
  • Vector Extension : none

Minimal Example

#include <iostream>

#include <Eigen/Core>

double f(const double x) { return 2 * x; }

int main() {

   Eigen::VectorXd v = Eigen::VectorXd::LinSpaced(10, 0, 9);
   std::cout << v.transpose() << std::endl;

   // works in Eigen 3.3, but not in 3.4 or master
   std::cout << v.unaryExpr(&f).transpose() << std::endl;

   // works well in all versions of Eigen (see quick reference guide)
   std::cout << v.unaryExpr(std::ptr_fun(f)).transpose() << std::endl;
   std::cout << v.unaryExpr(std::ref(f)).transpose() << std::endl;
   std::cout << v.unaryExpr([](double x) { return f(x); }).transpose()
             << std::endl;

   return EXIT_SUCCESS;
}

Steps to reproduce

  1. Save the above code snippet to file test_unaryExpr.cpp.
  2. Try to compile it using g++ -I ~/path/to/eigen/ -o test_unaryExpr test_unaryExpr.cpp with different versions of Eigen.

What is the current bug behavior?

The code does not compile and the main error message is

Eigen/src/Core/CoreEvaluators.h:595:9: error: base type ‘double (*)(double)’ fails to be a struct or class type
   class Data : private UnaryOp
         ^~~~

What is the expected correct behavior?

Code test_unaryExpr.cpp successfully compiles without warnings and program test_unaryExpr runs without errors.

Relevant logs

The expected output is

$ ./test_unaryExpr 
0 1 2 3 4 5 6 7 8 9
 0  2  4  6  8 10 12 14 16 18
 0  2  4  6  8 10 12 14 16 18
 0  2  4  6  8 10 12 14 16 18
 0  2  4  6  8 10 12 14 16 18
$

Related issues

Related issues might include #1700 and #1978.