Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:04:15

0001 #ifndef GeometryVector_newBasic2DVector_h
0002 #define GeometryVector_newBasic2DVector_h
0003 
0004 #include "DataFormats/GeometryVector/interface/Phi.h"
0005 #include "DataFormats/GeometryVector/interface/PreciseFloatType.h"
0006 #include "DataFormats/GeometryVector/interface/CoordinateSets.h"
0007 #include "DataFormats/Math/interface/SSEVec.h"
0008 
0009 #include <cmath>
0010 #include <iosfwd>
0011 
0012 template <class T>
0013 class Basic2DVector {
0014 public:
0015   typedef T ScalarType;
0016   typedef mathSSE::Vec2<T> VectorType;
0017   typedef mathSSE::Vec2<T> MathVector;
0018   typedef Geom::Polar2Cartesian<T> Polar;
0019 
0020   /** default constructor uses default constructor of T to initialize the 
0021    *  components. For built-in floating-point types this means initialization 
0022    * to zero
0023    */
0024   Basic2DVector() {}
0025 
0026   /// Copy constructor from same type. Should not be needed but for gcc bug 12685
0027   Basic2DVector(const Basic2DVector& p) : v(p.v) {}
0028 
0029   /// Assignment operator
0030   Basic2DVector& operator=(const Basic2DVector&) = default;
0031 
0032   template <typename U>
0033   Basic2DVector(const Basic2DVector<U>& p) : v(p.v) {}
0034 
0035   /** Explicit constructor from other (possibly unrelated) vector classes 
0036    *  The only constraint on the argument type is that it has methods
0037    *  x() and y(), and that these methods return a type convertible to T.
0038    *  Examples of use are
0039    *   <BR> construction from a Basic2DVector with different precision
0040    *   <BR> construction from a coordinate system converter 
0041    */
0042   template <class Other>
0043   explicit Basic2DVector(const Other& p) : v(p.x(), p.y()) {}
0044 
0045   /// construct from cartesian coordinates
0046   Basic2DVector(const T& x, const T& y) : v(x, y) {}
0047 
0048   // constructor from Vec2 or vec4
0049   template <typename U>
0050   Basic2DVector(mathSSE::Vec2<U> const& iv) : v(iv) {}
0051   template <typename U>
0052   Basic2DVector(mathSSE::Vec4<U> const& iv) : v(iv.xy()) {}
0053 
0054   MathVector const& mathVector() const { return v; }
0055   MathVector& mathVector() { return v; }
0056 
0057   T operator[](int i) const { return v[i]; }
0058   T& operator[](int i) { return v[i]; }
0059 
0060   /// Cartesian x coordinate
0061   T x() const { return v[0]; }
0062 
0063   /// Cartesian y coordinate
0064   T y() const { return v[1]; }
0065 
0066   /// The vector magnitude squared. Equivalent to vec.dot(vec)
0067   T mag2() const { return ::dot(v, v); }
0068 
0069   /// The vector magnitude. Equivalent to sqrt(vec.mag2())
0070   T mag() const { return std::sqrt(mag2()); }
0071 
0072   /// Radius, same as mag()
0073   T r() const { return mag(); }
0074 
0075   /** Azimuthal angle. The value is returned in radians, in the range (-pi,pi].
0076    *  Same precision as the system atan2(x,y) function.
0077    *  The return type is Geom::Phi<T>, see it's documentation.
0078    */
0079   T barePhi() const { return std::atan2(y(), x()); }
0080   Geom::Phi<T> phi() const { return Geom::Phi<T>(atan2(y(), x())); }
0081 
0082   /** Unit vector parallel to this.
0083    *  If mag() is zero, a zero vector is returned.
0084    */
0085   Basic2DVector unit() const {
0086     T my_mag = mag();
0087     return my_mag == 0 ? *this : *this / my_mag;
0088   }
0089 
0090   /** Operator += with a Basic2DVector of possibly different precision.
0091    */
0092   template <class U>
0093   Basic2DVector& operator+=(const Basic2DVector<U>& p) {
0094     v = v + p.v;
0095     return *this;
0096   }
0097 
0098   /** Operator -= with a Basic2DVector of possibly different precision.
0099    */
0100   template <class U>
0101   Basic2DVector& operator-=(const Basic2DVector<U>& p) {
0102     v = v - p.v;
0103     return *this;
0104   }
0105 
0106   /// Unary minus, returns a vector with components (-x(),-y(),-z())
0107   Basic2DVector operator-() const { return Basic2DVector(-v); }
0108 
0109   /// Scaling by a scalar value (multiplication)
0110   Basic2DVector& operator*=(T t) {
0111     v = v * t;
0112     return *this;
0113   }
0114 
0115   /// Scaling by a scalar value (division)
0116   Basic2DVector& operator/=(T t) {
0117     t = T(1) / t;
0118     v = v * t;
0119     return *this;
0120   }
0121 
0122   /// Scalar product, or "dot" product, with a vector of same type.
0123   T dot(const Basic2DVector& lh) const { return ::dot(v, lh.v); }
0124 
0125   /** Scalar (or dot) product with a vector of different precision.
0126    *  The product is computed without loss of precision. The type
0127    *  of the returned scalar is the more precise of the scalar types 
0128    *  of the two vectors.
0129    */
0130   template <class U>
0131   typename PreciseFloatType<T, U>::Type dot(const Basic2DVector<U>& lh) const {
0132     return Basic2DVector<typename PreciseFloatType<T, U>::Type>(*this).dot(
0133         Basic2DVector<typename PreciseFloatType<T, U>::Type>(lh));
0134   }
0135 
0136   /// Vector product, or "cross" product, with a vector of same type.
0137   T cross(const Basic2DVector& lh) const { return ::cross(v, lh.v); }
0138 
0139   /** Vector (or cross) product with a vector of different precision.
0140    *  The product is computed without loss of precision. The type
0141    *  of the returned scalar is the more precise of the scalar types 
0142    *  of the two vectors.
0143    */
0144   template <class U>
0145   typename PreciseFloatType<T, U>::Type cross(const Basic2DVector<U>& lh) const {
0146     return Basic2DVector<typename PreciseFloatType<T, U>::Type>(*this).cross(
0147         Basic2DVector<typename PreciseFloatType<T, U>::Type>(lh));
0148   }
0149 
0150 public:
0151   mathSSE::Vec2<T> v;
0152 };
0153 
0154 namespace geometryDetails {
0155   std::ostream& print2D(std::ostream& s, double x, double y);
0156 
0157 }
0158 
0159 /// simple text output to standard streams
0160 template <class T>
0161 inline std::ostream& operator<<(std::ostream& s, const Basic2DVector<T>& v) {
0162   return geometryDetails::print2D(s, v.x(), v.y());
0163 }
0164 
0165 /// vector sum and subtraction of vectors of possibly different precision
0166 template <class T>
0167 inline Basic2DVector<T> operator+(const Basic2DVector<T>& a, const Basic2DVector<T>& b) {
0168   return a.v + b.v;
0169 }
0170 template <class T>
0171 inline Basic2DVector<T> operator-(const Basic2DVector<T>& a, const Basic2DVector<T>& b) {
0172   return a.v - b.v;
0173 }
0174 
0175 template <class T, class U>
0176 inline Basic2DVector<typename PreciseFloatType<T, U>::Type> operator+(const Basic2DVector<T>& a,
0177                                                                       const Basic2DVector<U>& b) {
0178   typedef Basic2DVector<typename PreciseFloatType<T, U>::Type> RT;
0179   return RT(a) + RT(b);
0180 }
0181 
0182 template <class T, class U>
0183 inline Basic2DVector<typename PreciseFloatType<T, U>::Type> operator-(const Basic2DVector<T>& a,
0184                                                                       const Basic2DVector<U>& b) {
0185   typedef Basic2DVector<typename PreciseFloatType<T, U>::Type> RT;
0186   return RT(a) - RT(b);
0187 }
0188 
0189 // scalar product of vectors of same precision
0190 template <class T>
0191 inline T operator*(const Basic2DVector<T>& v1, const Basic2DVector<T>& v2) {
0192   return v1.dot(v2);
0193 }
0194 
0195 /// scalar product of vectors of different precision
0196 template <class T, class U>
0197 inline typename PreciseFloatType<T, U>::Type operator*(const Basic2DVector<T>& v1, const Basic2DVector<U>& v2) {
0198   return v1.dot(v2);
0199 }
0200 
0201 /** Multiplication by scalar, does not change the precision of the vector.
0202  *  The return type is the same as the type of the vector argument.
0203  */
0204 template <class T>
0205 inline Basic2DVector<T> operator*(const Basic2DVector<T>& v, T t) {
0206   return v.v * t;
0207 }
0208 
0209 /// Same as operator*( Vector, Scalar)
0210 template <class T>
0211 inline Basic2DVector<T> operator*(T t, const Basic2DVector<T>& v) {
0212   return v.v * t;
0213 }
0214 
0215 template <class T, class Scalar>
0216 inline Basic2DVector<T> operator*(const Basic2DVector<T>& v, const Scalar& s) {
0217   T t = static_cast<T>(s);
0218   return v * t;
0219 }
0220 
0221 /// Same as operator*( Vector, Scalar)
0222 template <class T, class Scalar>
0223 inline Basic2DVector<T> operator*(const Scalar& s, const Basic2DVector<T>& v) {
0224   T t = static_cast<T>(s);
0225   return v * t;
0226 }
0227 
0228 /** Division by scalar, does not change the precision of the vector.
0229  *  The return type is the same as the type of the vector argument.
0230  */
0231 template <class T>
0232 inline Basic2DVector<T> operator/(const Basic2DVector<T>& v, T t) {
0233   return v.v / t;
0234 }
0235 
0236 template <class T, class Scalar>
0237 inline Basic2DVector<T> operator/(const Basic2DVector<T>& v, const Scalar& s) {
0238   //   T t = static_cast<T>(Scalar(1)/s); return v*t;
0239   T t = static_cast<T>(s);
0240   return v / t;
0241 }
0242 
0243 typedef Basic2DVector<float> Basic2DVectorF;
0244 typedef Basic2DVector<double> Basic2DVectorD;
0245 
0246 #endif  // GeometryVector_Basic2DVector_h