Re: [eigen] XLC Port: Part II - External definition of a template member function of a template class causing the problems? |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [eigen] XLC Port: Part II - External definition of a template member function of a template class causing the problems?
- From: Aron Ahmadia <aja2111@xxxxxxxxxxxx>
- Date: Sat, 30 Jan 2010 17:38:45 +0300
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:sender:received:in-reply-to :references:date:x-google-sender-auth:message-id:subject:from:to :content-type:content-transfer-encoding; bh=9wULs4h2u4mdVYVFjwS0BL7WdXVBHnCSX4ov4wSvzu0=; b=GGCJ9tkr2STKZi31gDshzkZBd/WKP2OQzLaU1gh/PHnDwWlGsZ60IlsNRdZazpgBPC QBi2y38V/wYaXHPAKZgm4e2DzOXUjttYFCWWaoiOodlHf2Z1oEk0ySfU/nAo1/lwdZVG 5SChZ4nxzUb5I/0AEHsFix+8yzneqFUt/ggMI=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:content-type :content-transfer-encoding; b=B+P3LP7CwXnQsj4+2wX+vWdaQSCcQmIv19pvR2mXpDY+7JtmecUXytZfsJbbc8QMLg 3/wYE70WDTfqBVkJg3qTj5J7qg9pmSRE817ASVG/d0YpLY/0m3Tz+z1UUACbmESP6TA7 PUNj2+yqjXu0n5YOtszIdrOPWP5woMPCuP46Q=
still works:
aron@fen1:~/scratch% xlC -o bad_xlc4 bad_xlc4.cxx -I eigen/ -I
eigen/Eigen
[127]
aron@fen1:~/scratch% ./bad_xlc4
[0]
Doesn't have floating point.
Has floating point.
Has floating point.
A
On Sat, Jan 30, 2010 at 5:35 PM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx> wrote:
> And then try the same code but with the has_floating_point deferred
> until after they are used:
>
>
> #include<iostream>
>
> template<typename T> struct has_floating_point;
>
> template<typename T, bool IsFloat = has_floating_point<T>::ret>
> struct print_if_it_has_floating_point
> {
> static void run()
> {
> std::cout << "Doesn't have floating point." << std::endl;
> }
> };
>
> template<typename T>
> struct print_if_it_has_floating_point<T, true>
> {
> static void run()
> {
> std::cout << "Has floating point." << std::endl;
> }
> };
>
> template<>
> struct has_floating_point<int>
> {
> enum { ret = 0 };
> };
>
> template<>
> struct has_floating_point<float>
> {
> enum { ret = 1 };
> };
>
> template<>
> struct has_floating_point<double>
> {
> enum { ret = 1 };
> };
>
> int main()
> {
> print_if_it_has_floating_point<int>::run();
> print_if_it_has_floating_point<float>::run();
> print_if_it_has_floating_point<double>::run();
> }
>
>
>
>
> 2010/1/30 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
>> 2010/1/30 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
>>> 2010/1/30 Aron Ahmadia <aja2111@xxxxxxxxxxxx>:
>>>> Hi Benoit,
>>>>
>>>> I got that code workarounding by inlining the template function member
>>>> definitions into the class definition. I decided to skip forward and
>>>> see if there were any other big issues that were causing the XLC
>>>> compiler to crash, and ei_traits appears to be another one. The XLC
>>>> compiler is complaining when it tries to instansiate the ei_traits
>>>> template class using a single template argument (MatrixType) with the
>>>> error that the undefined class is not valid:
>>>>
>>>> "eigen/Eigen/src/Core/util/ForwardDeclarations.h", line 46.30:
>>>> 1540-1109 (S) The use of undefined class
>>>> "Eigen::ei_traits<Eigen::Matrix<float,3,3,0,3,3> >" is not valid.
>>>>
>>>> My suspicion is that ei_traits is not defined in a manner that XLC
>>>> approves of, or that it is bugging out for another reason. I will
>>>> spend some time investigating this week and try to narrow down exactly
>>>> how and where XLC is breaking. One possibility is that it can't
>>>> handle a template class instantiation to resolve another template
>>>> argument. Another possibility is that it can't find a definition of
>>>> ei_traits that it likes. I think I can eliminate the second
>>>> possibility by trying to explicitly instantiate an ei_traits object
>>>> with the given argument.s
>>>>
>>>> Nevermind, I just tried it. XLC is okay with this:
>>>> Eigen::ei_traits<Eigen::Matrix<float,3,3,0,3,3> > a;
>>>>
>>>> and compiles, links, and runs it through a main.cpp routine.
>>>> It gives the same errors about ei_traits with these lines of code:
>>>> Eigen::Matrix<float,3,3,0,3,3> m;
>>>> Matrix3f m3;
>>>>
>>>> "eigen/Eigen/src/Core/util/ForwardDeclarations.h", line 44.30:
>>>> 1540-1109 (S) The use of undefined class
>>>> "Eigen::ei_traits<Eigen::Matrix<float,3,3,0,3,3> >" is not valid.
>>>>
>>>> I think this points to your use of ei_traits here:
>>>> template<typename MatrixType, int BlockRows=Dynamic, int BlockCols=Dynamic,
>>>> int _DirectAccessStatus =
>>>> (ei_traits<MatrixType>::Flags&DirectAccessBit) ? HasDirectAccess :
>>>> NoDirectAccess> class Block;
>>>>
>>>> Some other compiler errors in the code seem to indicate that XLC is
>>>> unable to handle the instantiation of a template class to resolve a
>>>> non-class template argument.
>>>
>>> Ah, thanks, I'm starting to understand and this makes sense. I really
>>> hope that it is not the case:
>>>
>>>> that XLC is
>>>> unable to handle the instantiation of a template class to resolve a
>>>> non-class template argument.
>>>
>>> Because if that is the case, then it is virtually impossible to do any
>>> template metaprogramming with XLC :( At least I can say that we are
>>> doing this at many places and this is a very important device for us,
>>> so if that is what XLC doesn't like, fixing it would involve a very
>>> big set of changes and the resulting Eigen would be far clumsier
>>> (right now I'm not even sure that's possible).
>>
>> OK, can you try this testcase to see if XLC really has a problem with
>> the Eigen code that you pasted. This Eigen code is accessing an
>> instantiation of a template class to give the default value of a
>> template parameter. So here is a test case for that:
>>
>> #include<iostream>
>>
>> template<typename T> struct has_floating_point
>> {
>> enum { ret = 0 };
>> };
>>
>> template<>
>> struct has_floating_point<float>
>> {
>> enum { ret = 1 };
>> };
>>
>> template<>
>> struct has_floating_point<double>
>> {
>> enum { ret = 1 };
>> };
>>
>> template<typename T, bool IsFloat = has_floating_point<T>::ret>
>> struct print_if_it_has_floating_point
>> {
>> static void run()
>> {
>> std::cout << "Doesn't have floating point." << std::endl;
>> }
>> };
>>
>> template<typename T>
>> struct print_if_it_has_floating_point<T, true>
>> {
>> static void run()
>> {
>> std::cout << "Has floating point." << std::endl;
>> }
>> };
>>
>> int main()
>> {
>> print_if_it_has_floating_point<int>::run();
>> print_if_it_has_floating_point<float>::run();
>> print_if_it_has_floating_point<double>::run();
>> }
>>
>>
>> Benoit
>>
>>
>>
>>>
>>> Benoit
>>>
>>>
>>>>
>>>> Cheers,
>>>> Aron
>>>>
>>>> On Sat, Jan 30, 2010 at 4:56 PM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx> wrote:
>>>>> 2010/1/27 Aron Ahmadia <aja2111@xxxxxxxxxxxx>:
>>>>>> Hi all,
>>>>>>
>>>>>> I'm still looking at the port, and I've managed to narrow down the
>>>>>> problem. For those of you who've been following along at home, XLC
>>>>>> has been throwing this error when trying to compile the Eigen files:
>>>>>> [0]
>>>>>> "eigen/Eigen/src/Core/SelfAdjointView.h", line 147.81: 1540-0716 (S)
>>>>>> The template argument "Eigen::SelfAdjointView" does not match the
>>>>>> template parameter "class T".
>>>>>> "eigen/Eigen/src/Core/SelfAdjointView.h", line 134.112: 1540-0716 (S)
>>>>>> The template argument "Eigen::SelfAdjointView" does not match the
>>>>>> template parameter "class T".
>>>>>>
>>>>>> Suspiciously, there's no trace of SelfAdjointView being used as a
>>>>>> template parameter argument anywhere in there, or any trace of a
>>>>>> parameter named 'class T'.
>>>>>>
>>>>>> So I decided to create a new test file, slowly adding in the Eigen
>>>>>> header files from Core until I got compiler errors. Here's the
>>>>>> current file: http://pastebin.com/m267235e7
>>>>>>
>>>>>> If you'll notice, SelfAdjointView.h is being successfully included
>>>>>> here. What causes the breakage is SelfadjointProduct.h. This
>>>>>> actually isn't that surprising, since a function that declared in
>>>>>> SelfAdjointView.h is later defined in SelfadjointProduct.h (By the
>>>>>> way, should this be renamed to SelfAdjointProduct.h to fit the rest of
>>>>>> the naming scheme better?)
>>>>>>
>>>>>> Here is the declaration and the definition:
>>>>>>
>>>>>> template<typename DerivedU>
>>>>>> SelfAdjointView& rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha)
>>>>>>
>>>>>>
>>>>>> template<typename MatrixType, unsigned int UpLo>
>>>>>> template<typename DerivedU>
>>>>>> SelfAdjointView<MatrixType,UpLo>& SelfAdjointView<MatrixType,UpLo>
>>>>>> ::rankUpdate(const MatrixBase<DerivedU>& u, Scalar alpha)
>>>>>> {
>>>>>> typedef ei_blas_traits<DerivedU> UBlasTraits;
>>>>>> typedef typename UBlasTraits::DirectLinearAccessType ActualUType;
>>>>>> typedef typename ei_cleantype<ActualUType>::type _ActualUType;
>>>>>> const ActualUType actualU = UBlasTraits::extract(u.derived());
>>>>>>
>>>>>> Scalar actualAlpha = alpha * UBlasTraits::extractScalarFactor(u..derived());
>>>>>>
>>>>>> enum { IsRowMajor = (ei_traits<MatrixType>::Flags&RowMajorBit) ? 1 : 0 };
>>>>>>
>>>>>> ei_selfadjoint_product<Scalar,
>>>>>> _ActualUType::Flags&RowMajorBit ? RowMajor : ColMajor,
>>>>>> ei_traits<MatrixType>::Flags&RowMajorBit ? RowMajor : ColMajor,
>>>>>> !UBlasTraits::NeedToConjugate, UpLo>
>>>>>> ::run(_expression().cols(), actualU.cols(), &actualU.coeff(0,0),
>>>>>> actualU.stride(),
>>>>>> const_cast<Scalar*>(_expression().data()),
>>>>>> _expression().stride(), actualAlpha);
>>>>>>
>>>>>> return *this;
>>>>>> }
>>>>>>
>>>>>> So according to this page here:
>>>>>> http://www.comeaucomputing.com/techtalk/templates
>>>>>>
>>>>>> You're not allowed to do the above because SelfAdjointView is the
>>>>>> 'primary template argument'. Unfortunately, the code refuses to
>>>>>> compile if the template arguments are removed.
>>>>>
>>>>> I'm sorry, I still don't understand what is not allowed with the code
>>>>> that you pasted here?
>>>>>
>>>>> Benoit
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>
>>
>
>
>