Re: [eigen] Combining different types

On Fri, Sep 28, 2012 at 3:05 AM, Norman Goldstein wrote:
I understand that Eigen does not allow adding vectors of different types.  For example, the code

VectorXf    f(3);
VectorXd   d(3);

cout << (f+d) << endl;

yields the compilation error

YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY

I also understand the Eigen has this restriction because of the difficulty (correctness?) of doing vectorization with such expressions.  However, casting a float vector to a double vector is, of course, inefficient.  Does it make sense to move the prohibition of mixing types to be a pre-condition for vectorization, and allow the mixing of types in general in Eigen?

A concrete situation where this is desirable is where a bunch of parameters can be stored in a vector of floats (to save space), but the main calculations are done in double, to maintain sufficient precision.

The following template

template< typename A, typename B >
struct promote
{
typedef decltype( A(0) + B(0) ) type;
};

makes the promotion type explicit.  [In my actual situation, this does not work with a new scalar type, adouble (from ADOL-C) that I am using, but this can be handled by writing down specializations for the above template].

I have been able to, largely, work around the prohibition of mixing types with adouble by adding small amounts of code to specialize the existing Eigen infrastructure that does the checking.  However, I have not been able to solve this definitively, for adouble, and may need to (mildly) constrain my code, instead.  It would be more elegant if Eigen, from ground up, allowed the user the option to mix types

If I understand correctly, when you do double(5) * float(10) in C++, the float(10) is automatically converted/promoted to a double before the operation takes place. (For integer types, there's a whole list in order, from smallest to largest, unsigned following/"larger than" signed for a given size, and operands are converted to the later/"larger" of the two types.)  Sometimes this automatic promotion may lead to data loss (particularly if it's int to float, or signed int to unsigned larger int) and the compiler warns you. You can make the conversion explicit and acknowledge the limitations with static_cast<thetype>(arg).

My impression was that, in Eigen, since operations may #1. be more complicated/operate on larger data (making conversion overhead more substantial, etc) and #2. be more accuracy-focused than "general computing" (turn perhaps accidental mixing into errors so the code is clear about intent), automatic type-promotion operators for matrix types were not defined, requiring every mixing of matrices with differing scalar types to involve a .cast<type>() _expression_, serving a similar purposes as the static_cast in the scalar case above.

I'm not sure exactly what the .cast<type>() method actually does.  Based on a user's perspective for the library, I presume it just adds to the _expression_ tree, so conversion is lazily evaluated just like in the rest of Eigen. (that is, it wouldn't be converting the entire vector from float to double en-masse immediately)  However, I don't have enough experience with the innards to actually know if this is true or not.

--
Ryan Pavlik