This forum has been archived. All content is frozen. Please use KDE Discuss instead.

real/complex scalar type errors -- preventing temporaries

Tags: None
(comma "," separated)
danielbrake
Registered Member
Posts
15
Karma
0
Hi,
I am working to prevent Eigen from using implicit conversion on my custom numeric type, which is complex, and uses heap-allocated real and imaginary fields. That is, temporaries of complex type are detrimental to performance, and I need to mark all my constructors `explicit` if possible, which is what I am working on right now. Performance measurement indicates at least 10% of runtime is due to temporaries, so this is a worthwhile optimization.

I am working against Eigen 3.3.3 provided by Homebrew. I am currently finding at least three problem areas in Eigen, where a previously allowed implicit conversion is now causing problems when disallowed.

1. QR

Eigen/src/QR/ColPivHouseholderQR.h:509
Code: Select all
RealScalar threshold_helper =  numext::abs2<Scalar>(m_colNormsUpdated.maxCoeff() * NumTraits<Scalar>::epsilon()) / RealScalar(rows);

the template parameter to abs2 should not be Scalar, but RealScalar. If scalar is complex, this causes a lookup through
Code: Select all
inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)

which forces a conversion from real --> complex, eww. A nearly identical change should be made at 560:
Code: Select all
RealScalar temp2 = temp * numext::abs2<Scalar>(m_colNormsUpdated.coeffRef(j) /   // old code (new should be RealScalar

Making these two changes permits QR to compile correctly for me.

2. JacobiSVD

the SVD algorithm displays some type inconsistencies when using custom complex types with explicit-only constructors.
The instantiation is
Code: Select all
Eigen::internal::apply_rotation_in_the_plane<Eigen::Block<Eigen::Matrix<bertini::complex, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Block<Eigen::Matrix<bertini::complex, -1, -1, 0, -1, -1>, 1,
      -1, false>, boost::multiprecision::number<boost::multiprecision::backends::mpfr_float_backend<0, allocate_dynamic>, boost::multiprecision::expression_template_option::et_on> >

so the OtherScalar is a real type. so when line 333 comes around,
const Packet pc = pset1<Packet>(c);
`c` is a Real type, but there's no pset<complex>(real) function. so compilation fails.
changing the Packet to OtherPacket pushes the error lower in the code, to calls to `pmul` from the `conj_helper object` `pjc`, which I have not yet specialized in my codebase for Complex,Real. Chasing this type correction through JacobiSVD is getting a bit out of hand for me, so I will stop here and ask for help.

3. operator *= still doesn't work for complex-int arithmetic without implicit conversions, but I will leave that for another post.

This is a follow on to this post where I asked a question regarding using Eigen with a custom numeric type, particularly using the norm() function, and compile errors I got regarding `abs2`.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
Thank you for spotting these shortcomings.

Fixed in QR:
https://bitbucket.org/eigen/eigen/commits/3c4462767e36/

For JacobiSVD (this should also speedup JacobiSVD for std::complex<float/double> ;) ):
https://bitbucket.org/eigen/eigen/commits/8c3bb0011530/

I have not tried your settings with JacobiSVD but this should do the job. Let me know.
danielbrake
Registered Member
Posts
15
Karma
0
changes made april 14 solved those problems, thanks. i'll make a separate post later about why my *= aren't working with explicit-only conversions for my complex type.

thanks again!!!!
danielbrake
Registered Member
Posts
15
Karma
0
i followed up with an SO question https://stackoverflow.com/questions/43477416/custom-type-matrix-int-in-eigen regarding *= and explicit-only constructors.

thanks again, ggael, for all your help. you rule.


Bookmarks



Who is online

Registered users: abc72656, Bing [Bot], daret, Google [Bot], Sogou [Bot], Yahoo [Bot]