Re: [eigen] Combining different types

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


Thanks for the info.
I suppose, then, that I will complete the changes that I need to
allow  x+ax as well as ax+x .  I am happy to share what I have
done, but I am making the most use of C++11 as I can, and I expect
that when you (or we, with your help) get around to doing this properly
in Eigen, it will be done a lot more cleanly and elegantly.

Norm




On 10/03/2012 02:16 PM, Gael Guennebaud wrote:
Hi,

sorry for the late reply, just to say that we are aware of that
shortcoming, and some days I'd like to address it seriously. There are
some discussions there:
http://eigen.tuxfamily.org/bz/show_bug.cgi?id=279
http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2011/05/msg00038.html

gael

On Sat, Sep 29, 2012 at 6:47 PM, Norman Goldstein <normvcr@xxxxxxxxx> wrote:
The MatrixBase::cast() is very helpful, but I would like to point out how
using that does introduce non-trivial temporaries into my code.  For
example,

   double x;
   adouble ax; // adouble is a non-trivial class from the package ADOL-C

The sum   ax + x  is handled by operator+( adouble, double )  and results in
one temporary.
However, the sum   ax + adouble(x)  results in two temporaries:
1. The result of adouble(x), and
2. The result of operator+(adouble, adouble)

Fortunately, I was able to avoid the MatrixBase::cast(), in this case, by
introducing the following specialization

   namespace Eigen{ namespace internal {
   template<>
   struct functor_allows_mixing_real_and_complex
   < scalar_sum_op<adouble> > { enum { ret = 1 }; };
   } }

However, the story is not so straightforward for the sum in the opposite
order:   x + ax
I have analyzed this situation, but have not, yet, coded up a solution /
work-around.
I would appreciate any comments on this.

Many thanks,
Norm




On 09/28/2012 02:37 PM, Norman Goldstein wrote:

If the MatrixBase::cast() is, indeed, a lazy cast (I suspect you are right),
and does not actually instantiate a vector
of the new type, then that would be very helpful.  Thanks for your comments.


On 09/28/2012 12:30 PM, Ryan Pavlik wrote:



On Fri, Sep 28, 2012 at 3:05 AM, Norman Goldstein <normvcr@xxxxxxxxx> 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

Any comments much appreciated ...





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
HCI Graduate Student
Virtual Reality Applications Center
Iowa State University

rpavlik@xxxxxxxxxxx
http://academic.cleardefinition.com








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