Re: [eigen] Being able to use Eigen::Map<Eigen::Matrix< ... > > everywhere you can use a Eigen::Matrix |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen <eigen@xxxxxxxxxxxxxxxxxxx>
- Subject: Re: [eigen] Being able to use Eigen::Map<Eigen::Matrix< ... > > everywhere you can use a Eigen::Matrix
- From: Gael Guennebaud <gael.guennebaud@xxxxxxxxx>
- Date: Tue, 19 Feb 2013 19:37:43 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:mime-version:in-reply-to:references:from:date:message-id :subject:to:content-type; bh=RP3PuT9eGlux7NhM8xiDTGvguP8ZfV8aAa3uQvk2r38=; b=Nt8lm7T57/vkxfkNlq7108Ba1itlX5g+V4h+4279X1yLTjZEeBbdNR9pySb5/+kRy9 xW/S+SFh1DIgAEqiolFaZ8zZjiy2OMvaoN9SlbrP1NP3eDLF9neQqe+K84WP34QTtVW5 UUEiHkxozVBHw+iGaFhjXAr6loSY7bY7V9Baxk10B3Kn81o459IkVN5ksA9E8Zddtv0G LCJcTHoKPNRCovlBGvMuZTg6ZvX/lC1dWcbZRsYN0SnQjP/eG+UItVKUp7LrE2jrStdE Tk3+i4Wkgvwcut2DRu5D9RxIOryZdtDIt0bUQ3jjNEhwbCuNutODrLfQBv9i/9hiC46Q vIuA==
The way we handle this in Eigen is through static assertions. If you
can use c++11 features (e.g., -std=c++11 with gcc), then you can for
instance do in the body of your function:
static_assert(NumTraits<typename Db::Scalar>::IsInteger, "the second
argument of fit_params must hold integers");
See http://en.cppreference.com/w/cpp/language/static_assert.
Without c++11 you have to implement some workarounds. For instance,
you might have a look at the our StaticAssert.h file in src/Core/utils
and adapt a copy of it for your own use, or even use boost enable_if
(http://www.boost.org/doc/libs/1_53_0/libs/utility/enable_if.html).
And to complete Jitse answer, in the devel branch we have a tradeoff
between fully generic templated functions, and functions limited to
Matrix<> object via the Ref<> class which can accept any Matrix,
Block, Map and the likes of the a given scalar type:
http://eigen.tuxfamily.org/dox-devel/classEigen_1_1Ref.html.
cheers,
Gael
On Tue, Feb 19, 2013 at 3:02 PM, Malcolm Reynolds
<malcolm.reynolds@xxxxxxxxx> wrote:
> Now that I'm running through the code changes necessary to implement this -
> assuming my current functions are templated on the datatype of the matrix,
> how can I change them to use MatrixBase, but still make sure the type is
> correct?
>
> Eg:
>
> template<typename T>
> class Foo {
> public:
> inline void fit_params(const Matrix<T, Dynamic, Dynamic> & input_data,
> const Matrix<long, Dynamic, Dynamic> &
> valid_indices) {
>
> // stuff
> }
> };
>
> I want to make sure that the first argument is a matrix of whatever type the
> class is instantiated with, and the second matrix contains types which are
> valid for indexing. I can see that the function can be written as
>
> template<typename T>
> class Foo {
> public:
> template<typename Da, typename Db>
> inline void fit_params(const MatrixBase<Da> & input_data,
> const MatrixBase<Db> & valid_indices) {
>
> // stuff
> }
> };
>
> in order to get the efficiency advantages of MatrixBase, but now I can't
> specify that the second argument must have a scalar type suitable for
> indexing. Is there a way around this?
>
> Thanks again!
>
>
> On Tue, Feb 19, 2013 at 1:08 PM, Malcolm Reynolds
> <malcolm.reynolds@xxxxxxxxx> wrote:
>>
>> Hi Jitse,
>>
>> Thanks for your quick answer - excellent explanation. The way that C++ can
>> implicitly create temporary objects is definitely something I need to read
>> up more on. One final question, why do you recommend I use MatrixBase rather
>> than the more general DenseBase or EigenBase? Will using the more general
>> template types infer a performance hit?
>>
>> The only suggestion I would have for the documentation is maybe adding
>> some note to the "Mapping external arrays" section of
>> http://eigen.tuxfamily.org/dox-devel/group__QuickRefPage.html as that is the
>> main page I was using for reference. A little note there saying "to use Maps
>> in place of Matrices, please see considerations in <link>", with the link
>> pointing to the TopicFunctionTakingEigenTypes.html page, would be a good
>> idea I think.
>>
>> Thanks again!
>>
>> Malcolm
>>
>>
>> On Tue, Feb 19, 2013 at 10:30 AM, Jitse Niesen <jitse@xxxxxxxxxxxxxxxxx>
>> wrote:
>>>
>>> On Mon, 18 Feb 2013, Malcolm Reynolds wrote:
>>>
>>>> First post to this list, apologise if this is something really obvious
>>>> but
>>>> I'm having a bit of trouble using Eigen::Map. As I understand, it allows
>>>> me
>>>> to declare an Eigen matrix which reuses some memory already allocated
>>>> (in my
>>>> cases I'm gettin the data pointer from Numpy matrices), and then use
>>>> this
>>>> value everywhere I can use a regular Eigen matrix?
>>>
>>>
>>> All Eigen functions are written such that a Map can be used in the same
>>> way as a regular Eigen matrix. If you write your own functions, you may need
>>> to do something extra if you want your own functions to accept a Map instead
>>> of a regular matrix. This is explained at
>>>
>>> http://eigen.tuxfamily.org/dox-devel/TopicFunctionTakingEigenTypes.html
>>>
>>>
>>>> I have a function which I'd already written with the signature
>>>>
>>>> predict(const MatrixXd & features, MatrixXd * const labels_out)
>>>>
>>>> following the good practice (afaik) of using const refs for parameters
>>>> that
>>>> don't need to be modified, and pointers otherwise. Anyway I'd like to
>>>> pass
>>>> in Eigen::Maps for both arguments of this function, as I'm writing a
>>>> python
>>>> interface for my library. [...]
>>>
>>>
>>> You are calling this function like:
>>>
>>> Map<MatrixXd> mapFeatures = ...;
>>> Map<MatrixXd> mapLabels = ...;
>>> predict(mapFeatures, &mapLabels);
>>>
>>> For the first argument, the compiler converts the Map<MatrixXd> into a
>>> MatrixXd by introducing a temporary object, so it is as if you had written:
>>>
>>> MatrixXd tempObject(mapFeatures);
>>> predict(tempObject, &mapLabels);
>>>
>>> This does what you want, but it induces a performance penalty because
>>> when tempObject is constructed, all the data from mapFeatures is copied into
>>> the matrix tempObject.
>>>
>>> However, this does not work for the second argument. If the compiler were
>>> to introduce another temporary object and pass that as the second argument,
>>> then predict() would change the data in the temporary object and not in
>>> mapLabels.
>>>
>>> The solution is to have predict() accept arguments of the template type
>>> MatrixBase, as explained in the link I included above. If you still have
>>> questions after reading that, do not hesitate to ask. Any suggestions on how
>>> we can improve the explanations would be very welcome.
>>>
>>> Good luck,
>>> Jitse
>>>
>>>
>>
>