RE: [eigen] operator== (and probably others) for 0-sized Eigen-types

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


Hi Gael,

> I cannot reproduce the compilation issue with both gcc and clang. Here is what I tested:


I swapped rows and columns: The following example doesn't compile for me in the 2nd version:

#include <stdio.h>
#include <Eigen/Dense>

int main (int argc, char const *argv[])
{
  Eigen::Matrix<double, 1, 0> a;
  Eigen::Matrix<double, 1, 0> b;
  
  Eigen::Matrix<double, 0, 1> c;
  Eigen::Matrix<double, 0, 1> d;
  
  // works
  printf("%i\n", (int)(a == b));
  // broken
  printf("%i\n", (int)(c == d));
  return 0;
}



Best regards

Daniel Vollmer

--------------------------
Deutsches Zentrum für Luft- und Raumfahrt e.V. (DLR)
German Aerospace Center
Institute of Aerodynamics and Flow Technology | Lilienthalplatz 7 | 38108 Braunschweig | Germany
From: Gael Guennebaud [gael.guennebaud@xxxxxxxxx]
Sent: Monday, November 11, 2013 23:59
To: eigen
Subject: Re: [eigen] operator== (and probably others) for 0-sized Eigen-types


Hi,


#include <Eigen/Core>
#include <iostream>
int main() {
  Eigen::Matrix<double, 1, 0> A, B;
  std::cout << (A == B) << "\n";
};

However, it currently returns false, while returning true seems to be more appropriate. Actually the problem might be more general because it raises the question of what should be the result of .all() and .any() on an empty matrix of bool? Currently both returns false, that is why operator== returns false too since A==B on Matrices is implemented as:

(A.array()==B.array()).all()

One option could be to make .all() and .any() returns the identity element of the operators && and || respectively, i.e., true and false. This choice would even be compatible with the following identities:

(A.array()==B.array()).all()  <=> (A==B)

(A.array()!=B.array()).any()  <=> (A!=B)

However it would break a more fundamental identity that is:

_expression_.all() => _expression_.any()

Moreover, it seems to me that an 'ideal' result of all() and any() on zero-sized objects depend on the context, e.g:

(A.array()==B.array()).all() == (A.array()==B.array()).any() == true

(A.array()!=B.array()).all() == (A.array()!=B.array()).any() == false

Therefore, perhaps it would be safer to disallow 'all' and 'any' on zero-sized object, and specialize operator== and operator!= on matrices for them?

(I'm very tired, so maybe I've missed something obvious here)

cheers,
gael



On Mon, Nov 11, 2013 at 6:30 PM, <Daniel.Vollmer@xxxxxx> wrote:
Hello,

while playing with Eigen in the context of rather generic template code, I stumbled upon
the following issue when comparing two fixed, zero-sized Vectors for equality:

In file included from /Users/maven/Development/dlr/dx/negev/thirdparty/eigen-3.2.0/Eigen/Dense:1:
In file included from /Users/maven/Development/dlr/dx/negev/thirdparty/eigen-3.2.0/Eigen/Core:344:
/Users/maven/Development/dlr/dx/negev/thirdparty/eigen-3.2.0/Eigen/src/Core/BooleanRedux.h:21:11: error: _expression_ is not an integral constant _expression_
    col = (UnrollCount-1) / Derived::RowsAtCompileTime,
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/maven/Development/dlr/dx/negev/thirdparty/eigen-3.2.0/Eigen/src/Core/BooleanRedux.h:88:22: note: in instantiation of template class 'Eigen::internal::all_unroller<Eigen::CwiseBinaryOp<std::__1::equal_to<double>, const Eigen::Matrix<double, 0, 1, 0, 0, 1>, const Eigen::Matrix<double, 0, 1, 0, 0, 1> >, 0>' requested here
    return internal::all_unroller<Derived, unroll ? int(SizeAtCompileTime) : Dynamic>::run(derived());
                     ^
/Users/maven/Development/dlr/dx/negev/thirdparty/eigen-3.2.0/Eigen/src/Core/MatrixBase.h:294:32: note: in instantiation of member function 'Eigen::DenseBase<Eigen::CwiseBinaryOp<std::__1::equal_to<double>, const Eigen::Matrix<double, 0, 1, 0, 0, 1>, const Eigen::Matrix<double, 0, 1, 0, 0, 1> > >::all' requested here
    { return cwiseEqual(other).all(); }
                               ^
/Users/maven/Development/dlr/dx/negev/thirdparty/gtest-gmock-1.7.0/gtest/gtest.h:18861:16: note: in instantiation of function template specialization 'Eigen::MatrixBase<Eigen::Matrix<double, 0, 1, 0, 0, 1> >::operator==<Eigen::Matrix<double, 0, 1, 0, 0, 1> >' requested here
  if (expected == actual) {
               ^
/Users/maven/Development/dlr/dx/negev/thirdparty/gtest-gmock-1.7.0/gtest/gtest.h:18897:12: note: in instantiation of function template specialization 'testing::internal::CmpHelperEQ<DX::FixedArray1D<double, 0>, DX::FixedArray1D<double, 0> >' requested here
    return CmpHelperEQ(expected_expression, actual_expression, expected,
           ^
.../test/DiscreteEquation/NamedSetTest.cpp:133:3: note: in instantiation of function template specialization 'testing::internal::EqHelper<false>::Compare<DX::FixedArray1D<double, 0>, DX::FixedArray1D<double, 0> >' requested here
  EXPECT_EQ(arr, ns.Select(typename NS::FormatT()).CopyIntoArray());

(i.e. Eigen::Matrix<double, 1, 0>() == Eigen::Matrix<double, 1, 0>())

Before trying an Eigen::Matrix, I'd simply used std::array, and that works fine even
in the degenerate case with 0 entries.

Is this desired behaviour? Without thinking about it too much (as the compare is done by value)
it maybe should return true in this case...?


Best regards

Daniel Vollmer

--------------------------
Deutsches Zentrum für Luft- und Raumfahrt e.V. (DLR)
German Aerospace Center
Institute of Aerodynamics and Flow Technology | Lilienthalplatz 7 | 38108 Braunschweig | Germany





Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/