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
|