-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Extend templation in GenVector to better support vectorised Vc types. #394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 26 commits
76a8f9d
7e9c2b7
b15d62a
2b2fc17
2e74f0d
c3175c6
9bdfb8e
c97245c
f12d368
bbbbbd0
9a0ee77
371d50d
dcb0b30
29e7e30
14e73b4
27bbb57
196a00b
0ad5828
1928c75
5ccdaea
ef1aea9
6cac16a
68ba28a
939b7cb
d9b810b
776ce1a
fbe74d2
12b43b0
8367bdf
0f404ba
65a701d
4ba8a1b
ff94a5a
b8ca822
b32cb6a
febe783
a628a2a
89b2d26
6bf0368
bd96bd0
dea8d05
a18221a
eb0b8ed
7da1945
a271eab
decbe11
58c6315
17f42a3
434396d
b145899
ad8d3a5
b018a03
bb1e386
1786383
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,7 +84,6 @@ public : | |
| return *this; | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| Set internal data based on an array of 3 Scalar numbers | ||
| */ | ||
|
|
@@ -111,15 +110,17 @@ public : | |
| Scalar Z() const { return fZ;} | ||
| Scalar Mag2() const { return fX*fX + fY*fY + fZ*fZ;} | ||
| Scalar Perp2() const { return fX*fX + fY*fY ;} | ||
| Scalar Rho() const { return std::sqrt( Perp2());} | ||
| Scalar R() const { return std::sqrt( Mag2());} | ||
| Scalar Theta() const { return (fX==0 && fY==0 && fZ==0) ? | ||
| 0 : atan2(Rho(),Z());} | ||
| Scalar Phi() const { return (fX==0 && fY==0) ? 0 : atan2(fY,fX);} | ||
| Scalar Rho() const { using namespace std; return sqrt( Perp2() ); } | ||
| Scalar R() const { using namespace std; return sqrt( Mag2() ); } | ||
| Scalar Theta() const { using namespace std; | ||
| return (fX==Scalar(0) && fY==Scalar(0) && fZ==Scalar(0)) ? | ||
| Scalar(0) : atan2(Rho(),Z());} | ||
| Scalar Phi() const { using namespace std; | ||
| return (fX==Scalar(0) && fY==Scalar(0)) ? Scalar(0) : atan2(fY,fX);} | ||
|
|
||
| // pseudorapidity | ||
| Scalar Eta() const { | ||
| return Impl::Eta_FromRhoZ ( Rho(),fZ); | ||
| return Impl::Eta_FromRhoZ( Rho(), fZ ); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -149,7 +150,7 @@ public : | |
| /** | ||
| scale the vector by a scalar quantity a | ||
| */ | ||
| void Scale(Scalar a) { fX *= a; fY *= a; fZ *= a; } | ||
| void Scale(Scalar a) { fX *= a; fY *= a; fZ *= a; } | ||
|
|
||
| /** | ||
| negate the vector | ||
|
|
@@ -190,10 +191,11 @@ public : | |
| template <class T2> | ||
| explicit Cartesian3D( const Polar3D<T2> & v ) : fZ (v.Z()) | ||
| { | ||
| T rho = v.Rho(); // re-using this instead of calling v.X() and v.Y() | ||
| // is the speed improvement | ||
| fX = rho * std::cos(v.Phi()); | ||
| fY = rho * std::sin(v.Phi()); | ||
| using namespace std; | ||
| const T rho = v.Rho(); // re-using this instead of calling v.X() and v.Y() | ||
| // is the speed improvement | ||
|
||
| fX = rho * cos(v.Phi()); | ||
|
||
| fY = rho * sin(v.Phi()); | ||
| } | ||
| // Technical note: This works even though only Polar3Dfwd.h is | ||
| // included (and in fact, including Polar3D.h would cause circularity | ||
|
|
@@ -203,9 +205,10 @@ public : | |
| template <class T2> | ||
| Cartesian3D & operator = (const Polar3D<T2> & v) | ||
| { | ||
| T rho = v.Rho(); | ||
| fX = rho * std::cos(v.Phi()); | ||
| fY = rho * std::sin(v.Phi()); | ||
| using namespace std; | ||
| const T rho = v.Rho(); | ||
| fX = rho * cos(v.Phi()); | ||
| fY = rho * sin(v.Phi()); | ||
| fZ = v.Z(); | ||
| return *this; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -249,11 +249,11 @@ namespace ROOT { | |
| */ | ||
| template <class IT> | ||
| void GetCoordinates( IT begin) const { | ||
| Scalar a,b,c = 0; | ||
| GetCoordinates (a,b,c); | ||
| *begin++ = a; | ||
| *begin++ = b; | ||
| *begin = c; | ||
| Scalar a,b,c = Scalar(0); | ||
|
||
| GetCoordinates (a,b,c); | ||
| *begin++ = a; | ||
| *begin++ = b; | ||
| *begin = c; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -262,8 +262,8 @@ namespace ROOT { | |
| then (x, y, z) are converted to that form) | ||
| */ | ||
| DisplacementVector3D<CoordSystem, Tag>& SetXYZ (Scalar a, Scalar b, Scalar c) { | ||
| fCoordinates.SetXYZ(a,b,c); | ||
| return *this; | ||
| fCoordinates.SetXYZ(a,b,c); | ||
| return *this; | ||
| } | ||
|
|
||
| // ------------------- Equality ----------------- | ||
|
|
@@ -333,13 +333,26 @@ namespace ROOT { | |
| Scalar Perp2() const { return fCoordinates.Perp2();} | ||
|
|
||
| /** | ||
| return unit vector parallel to this | ||
| return unit vector parallel to this (scalar) | ||
| */ | ||
| DisplacementVector3D Unit() const { | ||
| Scalar tot = R(); | ||
| template< typename SCALAR = Scalar > | ||
|
||
| typename std::enable_if< std::is_arithmetic<SCALAR>::value, DisplacementVector3D >::type | ||
| Unit() const { | ||
| const auto tot = R(); | ||
| return tot == 0 ? *this : DisplacementVector3D(*this) / tot; | ||
| } | ||
|
|
||
| /** | ||
| return unit vector parallel to this (scalar) | ||
| */ | ||
| template< typename SCALAR = Scalar > | ||
| typename std::enable_if< !std::is_arithmetic<SCALAR>::value, DisplacementVector3D >::type | ||
| Unit() const { | ||
| SCALAR tot = R(); | ||
| tot( tot == SCALAR(0) ) = SCALAR(1); | ||
| return DisplacementVector3D(*this) / tot; | ||
| } | ||
|
|
||
| // ------ Setting of individual elements present in coordinate system ------ | ||
|
|
||
| /** | ||
|
|
@@ -620,35 +633,52 @@ namespace ROOT { | |
| // ------------- I/O to/from streams ------------- | ||
|
|
||
| template< class char_t, class traits_t, class T, class U > | ||
| inline | ||
| std::basic_ostream<char_t,traits_t> & | ||
| operator << ( std::basic_ostream<char_t,traits_t> & os | ||
| inline | ||
| typename std::enable_if< std::is_arithmetic<typename DisplacementVector3D<T,U>::Scalar>::value, | ||
| std::basic_ostream<char_t,traits_t> & >::type | ||
| operator << ( std::basic_ostream<char_t,traits_t> & os | ||
| , DisplacementVector3D<T,U> const & v | ||
| ) | ||
| { | ||
| if( !os ) return os; | ||
|
|
||
| typename T::Scalar a, b, c; | ||
| v.GetCoordinates(a, b, c); | ||
|
|
||
| if( detail::get_manip( os, detail::bitforbit ) ) { | ||
| detail::set_manip( os, detail::bitforbit, '\00' ); | ||
| typedef GenVector_detail::BitReproducible BR; | ||
| BR::Output(os, a); | ||
| BR::Output(os, b); | ||
| BR::Output(os, c); | ||
| if ( os ) { | ||
|
|
||
| typename T::Scalar a, b, c; | ||
| v.GetCoordinates(a, b, c); | ||
|
|
||
| if( detail::get_manip( os, detail::bitforbit ) ) { | ||
| detail::set_manip( os, detail::bitforbit, '\00' ); | ||
| typedef GenVector_detail::BitReproducible BR; | ||
| BR::Output(os, a); | ||
| BR::Output(os, b); | ||
| BR::Output(os, c); | ||
| } | ||
| else { | ||
| os << detail::get_manip( os, detail::open ) << a | ||
| << detail::get_manip( os, detail::sep ) << b | ||
| << detail::get_manip( os, detail::sep ) << c | ||
| << detail::get_manip( os, detail::close ); | ||
| } | ||
| } | ||
| else { | ||
| os << detail::get_manip( os, detail::open ) << a | ||
| << detail::get_manip( os, detail::sep ) << b | ||
| << detail::get_manip( os, detail::sep ) << c | ||
| << detail::get_manip( os, detail::close ); | ||
| } | ||
|
|
||
| return os; | ||
|
|
||
| } // op<< <>() | ||
|
|
||
| template< class char_t, class traits_t, class T, class U > | ||
| inline | ||
| typename std::enable_if< !std::is_arithmetic<typename DisplacementVector3D<T,U>::Scalar>::value, | ||
| std::basic_ostream<char_t,traits_t> & >::type | ||
| operator << ( std::basic_ostream<char_t,traits_t> & os | ||
| , DisplacementVector3D<T,U> const & v | ||
| ) | ||
| { | ||
| if ( os ) { | ||
| os << "{ "; | ||
| for ( std::size_t i = 0; i < PositionVector3D<T,U>::Scalar::Size; ++i ) { | ||
| os << "(" << v.x()[i] << "," << v.y()[i] << "," << v.z()[i] << ") "; | ||
| } | ||
| os << "}"; | ||
| } | ||
| return os; | ||
| } // op<< <>() | ||
|
|
||
| template< class char_t, class traits_t, class T, class U > | ||
| inline | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, what is the advantage of the
using namespace std;pattern, instead of usingreturn std::sqrt...?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is required to support Vc types. For Vc types you need to use the versions of sqrt etc. shipped as part of that library. Using std::sqrt does not allow this. The namespace trick means you use the std:: versions when appropriate, but also allows other implementations when not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, thanks for explaining! Neat and subtle at the same time. Btw, there is an inherited extra space after the open paren.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, it's @lmoneta's call but I'd prefer to have a short comment saying what the pattern does, or maybe a #define R__enable_vc_types using namespace std; This would make this easier to read by an unarmed eye.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dislike preprocessor directives unless absolutely required, and I don't think here adding one really helps. To my eye the pattern as is is clear, but as you say its up to @lmoneta . I would be OK with adding some sort of comment somewhere ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a comment would be as clear and more concise than a ifdef
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
I don't understand this. Are you sure it is needed for Vc ? In the past I have seen Vc replacing automatically its vectorised function implementations in the std namespace
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am sure I ran into some issue that lead me to doing this... Also note the templation is in principle there for other types than Vc. This change in principle supports types that do not extend the math functions under std::, as well as those that do.