rivet is hosted by Hepforge, IPPP Durham
VectorN.hh
Go to the documentation of this file.
00001 #ifndef RIVET_MATH_VECTORN
00002 #define RIVET_MATH_VECTORN
00003 
00004 #include "Rivet/Math/MathHeader.hh"
00005 #include "Rivet/Math/MathUtils.hh"
00006 
00007 #include "Rivet/Math/eigen/vector.h"
00008 
00009 namespace Rivet {
00010 
00011 
00012   template <size_t N>
00013   class Vector;
00014   template <size_t N>
00015   class Matrix;
00016 
00017   template <size_t N>
00018   Vector<N> multiply(const Matrix<N>& a, const Vector<N>& b);
00019 
00020 
00021   /// A minimal base class for \f$ N \f$-dimensional vectors.
00022   template <size_t N>
00023   class Vector {
00024     template <size_t M>
00025     friend Vector<M> multiply(const Matrix<M>& a, const Vector<M>& b);
00026 
00027   public:
00028     Vector() { _vec.loadZero(); }
00029 
00030     Vector(const Vector<N>& other)
00031       : _vec(other._vec) { }
00032 
00033     const double& get(const size_t index) const {
00034       if (index >= N) {
00035         throw std::runtime_error("Tried to access an invalid vector index.");
00036       } else {
00037         return _vec(index);
00038       }
00039     }
00040 
00041     /// Direct access to vector elements by index.
00042     const double& operator[](const size_t index) const {
00043       return get(index);
00044     }
00045 
00046     /// Direct access to vector elements by index.
00047     double& operator[](const size_t index) {
00048       return get(index);
00049     }
00050 
00051     /// Set indexed value
00052     Vector<N>& set(const size_t index, const double value) {
00053       if (index >= N) {
00054         throw std::runtime_error("Tried to access an invalid vector index.");
00055       } else {
00056         _vec[index] = value;
00057       }
00058       return *this;
00059     }
00060 
00061     /// Vector dimensionality
00062     size_t size() const {
00063       return N;
00064     }
00065 
00066     /// Check for nullness, allowing for numerical precision
00067     bool isZero(double tolerance=1E-5) const {
00068       for (size_t i=0; i < N; ++i) {
00069         if (! Rivet::isZero(_vec[i], tolerance) ) return false;
00070       }
00071       return true;
00072     }
00073 
00074     /// @brief Calculate the modulus-squared of a vector.
00075     /// \f$ \sum_{i=1}^N x_i^2 \f$.
00076     double mod2() const {
00077       double mod2 = 0.0;
00078       for (size_t i = 0; i < size(); ++i) {
00079         const double element = get(i);
00080         mod2 += element*element;
00081       }
00082       return mod2;
00083     }
00084 
00085     /// @brief Calculate the modulus of a vector.
00086     /// \f$ \sqrt{\sum_{i=1}^N x_i^2} \f$.
00087     double mod() const {
00088       const double norm = mod2();
00089       assert(norm >= 0);
00090       return sqrt(norm);
00091     }
00092 
00093     /// Invert the vector
00094     Vector<N> operator-() const {
00095       Vector<N> rtn;
00096       rtn._vec = -_vec;
00097       return rtn;
00098     }
00099 
00100     bool operator==(const Vector<N>& a) const {
00101       return _vec == a._vec;
00102     }
00103 
00104     bool operator!=(const Vector<N>& a) const {
00105       return _vec != a._vec;
00106     }
00107 
00108     bool operator<(const Vector<N>& a) const {
00109       return _vec < a._vec;
00110     }
00111 
00112     bool operator<=(const Vector<N>& a) const {
00113       return _vec <= a._vec;
00114     }
00115 
00116     bool operator>(const Vector<N>& a) const {
00117       return _vec > a._vec;
00118     }
00119 
00120     bool operator>=(const Vector<N>& a) const {
00121       return _vec >= a._vec;
00122     }
00123 
00124 
00125   protected:
00126     double& get(const size_t index) {
00127       if (index >= N) {
00128         throw std::runtime_error("Tried to access an invalid vector index.");
00129       } else {
00130         return _vec(index);
00131       }
00132     }
00133 
00134     /// Vector
00135     Eigen::Vector<double,N> _vec;
00136   };
00137 
00138 
00139 
00140   /// Calculate the modulus-squared of a vector.
00141   /// \f$ \sum_{i=1}^N x_i^2 \f$.
00142   template <size_t N>
00143   inline double mod2(const Vector<N>& v) {
00144     return v.mod2();
00145   }
00146 
00147   /// Calculate the modulus of a vector.
00148   /// \f$ \sqrt{\sum_{i=1}^N x_i^2} \f$.
00149   template <size_t N>
00150   inline double mod(const Vector<N>& v) {
00151     return v.mod();
00152   }
00153 
00154 
00155   /////////////////////////////////////////////////
00156 
00157 
00158   /// @name String representations of vectors
00159   //@{
00160 
00161   /// Make string representation
00162   template <size_t N>
00163   inline const string toString(const Vector<N>& v) {
00164     ostringstream out;
00165     out << "(";
00166     for (size_t i = 0; i < v.size(); ++i) {
00167       out << (fabs(v[i]) < 1E-30 ? 0.0 : v[i]);
00168       if (i < v.size()-1) out << ", ";
00169     }
00170     out << ")";
00171     return out.str();
00172   }
00173 
00174   /// Stream out string representation
00175   template <size_t N>
00176   inline std::ostream& operator<<(std::ostream& out, const Vector<N>& v) {
00177     out << toString(v);
00178     return out;
00179   }
00180 
00181   //@}
00182 
00183 
00184   /////////////////////////////////////////////////
00185 
00186 
00187   /// Compare two vectors by index, allowing for numerical precision
00188   template <size_t N>
00189   inline bool fuzzyEquals(const Vector<N>& va, const Vector<N>& vb, double tolerance=1E-5) {
00190     for (size_t i = 0; i < N; ++i) {
00191       const double a = va.get(i);
00192       const double b = vb.get(i);
00193       if (!Rivet::fuzzyEquals(a, b, tolerance)) return false;
00194     }
00195     return true;
00196   }
00197 
00198 
00199   /// External form of numerically safe nullness check
00200   template <size_t N>
00201   inline bool isZero(const Vector<N>& v, double tolerance=1E-5) {
00202     return v.isZero(tolerance);
00203   }
00204 
00205 
00206 }
00207 
00208 #endif