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 ]


BTW: Thanks for the test cases.  It really does help narrow down and
eliminate causes.  It should be possible to build a slightly more
complex example that fails in a similar manner to the main Eigen code
to isolate exactly what xlc is choking on.

A

On Sat, Jan 30, 2010 at 5:38 PM, Aron Ahmadia <aja2111@xxxxxxxxxxxx> wrote:
> 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
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>>
>>
>



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