Rivet  3.1.3
MatrixN.hh
1 #ifndef RIVET_MATH_MATRIXN
2 #define RIVET_MATH_MATRIXN
3 
4 #include "Rivet/Math/MathConstants.hh"
5 #include "Rivet/Math/MathUtils.hh"
6 #include "Rivet/Math/Vectors.hh"
7 
8 #include "Rivet/Math/eigen3/Dense"
9 
10 namespace Rivet {
11 
12 
13  template <size_t N>
14  class Matrix;
15  typedef Matrix<4> Matrix4;
16 
17  template <size_t N>
18  Matrix<N> multiply(const Matrix<N>& a, const Matrix<N>& b);
19  template <size_t N>
20  Matrix<N> divide(const Matrix<N>&, const double);
21  template <size_t N>
22  Matrix<N> operator*(const Matrix<N>& a, const Matrix<N>& b);
23 
24 
26 
27 
29  template <size_t N>
30  class Matrix {
31  template <size_t M>
32  friend Matrix<M> add(const Matrix<M>&, const Matrix<M>&);
33  template <size_t M>
34  friend Matrix<M> multiply(const double, const Matrix<M>&);
35  template <size_t M>
36  friend Matrix<M> multiply(const Matrix<M>&, const Matrix<M>&);
37  template <size_t M>
38  friend Vector<M> multiply(const Matrix<M>&, const Vector<M>&);
39  template <size_t M>
40  friend Matrix<M> divide(const Matrix<M>&, const double);
41 
42  public:
43  static Matrix<N> mkZero() {
44  Matrix<N> rtn;
45  return rtn;
46  }
47 
48  static Matrix<N> mkDiag(Vector<N> diag) {
49  Matrix<N> rtn;
50  for (size_t i = 0; i < N; ++i) {
51  rtn.set(i, i, diag[i]);
52  }
53  return rtn;
54  }
55 
56  static Matrix<N> mkIdentity() {
57  Matrix<N> rtn;
58  for (size_t i = 0; i < N; ++i) {
59  rtn.set(i, i, 1);
60  }
61  return rtn;
62  }
63 
64 
65  public:
66 
67  Matrix() : _matrix(EMatrix::Zero()) {}
68 
69  Matrix(const Matrix<N>& other) : _matrix(other._matrix) {}
70 
71  Matrix& set(const size_t i, const size_t j, const double value) {
72  if (i < N && j < N) {
73  _matrix(i, j) = value;
74  } else {
75  throw std::runtime_error("Attempted set access outside matrix bounds.");
76  }
77  return *this;
78  }
79 
80  double get(const size_t i, const size_t j) const {
81  if (i < N && j < N) {
82  return _matrix(i, j);
83  } else {
84  throw std::runtime_error("Attempted get access outside matrix bounds.");
85  }
86  }
87 
88  Vector<N> getRow(const size_t row) const {
89  Vector<N> rtn;
90  for (size_t i = 0; i < N; ++i) {
91  rtn.set(i, _matrix(row,i));
92  }
93  return rtn;
94  }
95 
96  Matrix<N>& setRow(const size_t row, const Vector<N>& r) {
97  for (size_t i = 0; i < N; ++i) {
98  _matrix(row,i) = r.get(i);
99  }
100  return *this;
101  }
102 
103  Vector<N> getColumn(const size_t col) const {
104  Vector<N> rtn;
105  for (size_t i = 0; i < N; ++i) {
106  rtn.set(i, _matrix(i,col));
107  }
108  return rtn;
109  }
110 
111  Matrix<N>& setColumn(const size_t col, const Vector<N>& c) {
112  for (size_t i = 0; i < N; ++i) {
113  _matrix(i,col) = c.get(i);
114  }
115  return *this;
116  }
117 
118  Matrix<N> transpose() const {
119  Matrix<N> tmp;
120  tmp._matrix = _matrix.transpose();
121  return tmp;
122  }
123 
124  // Matrix<N>& transposeInPlace() {
125  // _matrix.replaceWithAdjoint();
126  // return *this;
127  // }
128 
130  Matrix<N> inverse() const {
131  Matrix<N> tmp;
132  tmp._matrix = _matrix.inverse();
133  return tmp;
134  }
135 
137  double det() const {
138  return _matrix.determinant();
139  }
140 
142  double trace() const {
143  double tr = 0.0;
144  for (size_t i = 0; i < N; ++i) {
145  tr += _matrix(i,i);
146  }
147  return tr;
148  // return _matrix.trace();
149  }
150 
153  Matrix<N> rtn;
154  rtn._matrix = -_matrix;
155  return rtn;
156  }
157 
159  constexpr size_t size() const {
160  return N;
161  }
162 
164  bool isZero(double tolerance=1E-5) const {
165  for (size_t i=0; i < N; ++i) {
166  for (size_t j=0; j < N; ++j) {
167  if (! Rivet::isZero(_matrix(i,j), tolerance) ) return false;
168  }
169  }
170  return true;
171  }
172 
174  bool isEqual(Matrix<N> other) const {
175  for (size_t i=0; i < N; ++i) {
176  for (size_t j=i; j < N; ++j) {
177  if (! Rivet::isZero(_matrix(i,j) - other._matrix(i,j)) ) return false;
178  }
179  }
180  return true;
181  }
182 
184  bool isSymm() const {
185  return isEqual(this->transpose());
186  }
187 
189  bool isDiag() const {
190  for (size_t i=0; i < N; ++i) {
191  for (size_t j=0; j < N; ++j) {
192  if (i == j) continue;
193  if (! Rivet::isZero(_matrix(i,j)) ) return false;
194  }
195  }
196  return true;
197  }
198 
199  bool operator == (const Matrix<N>& a) const {
200  return _matrix == a._matrix;
201  }
202 
203  bool operator != (const Matrix<N>& a) const {
204  return _matrix != a._matrix;
205  }
206 
207  // bool operator < (const Matrix<N>& a) const {
208  // return _matrix < a._matrix;
209  // }
210 
211  // bool operator <= (const Matrix<N>& a) const {
212  // return _matrix <= a._matrix;
213  // }
214 
215  // bool operator > (const Matrix<N>& a) const {
216  // return _matrix > a._matrix;
217  // }
218 
219  // bool operator >= (const Matrix<N>& a) const {
220  // return _matrix >= a._matrix;
221  // }
222 
223  Matrix<N>& operator *= (const Matrix<N>& m) {
224  _matrix *= m._matrix;
225  return *this;
226  }
227 
228  Matrix<N>& operator *= (const double a) {
229  _matrix *= a;
230  return *this;
231  }
232 
233  Matrix<N>& operator /= (const double a) {
234  _matrix /= a;
235  return *this;
236  }
237 
238  Matrix<N>& operator += (const Matrix<N>& m) {
239  _matrix += m._matrix;
240  return *this;
241  }
242 
243  Matrix<N>& operator -= (const Matrix<N>& m) {
244  _matrix -= m._matrix;
245  return *this;
246  }
247 
248  protected:
249 
250  using EMatrix = Eigen::Matrix<double,N,N>;
251  EMatrix _matrix;
252 
253  };
254 
255 
257 
258 
259  template <size_t N>
260  inline Matrix<N> add(const Matrix<N>& a, const Matrix<N>& b) {
261  Matrix<N> result;
262  result._matrix = a._matrix + b._matrix;
263  return result;
264  }
265 
266  template <size_t N>
267  inline Matrix<N> subtract(const Matrix<N>& a, const Matrix<N>& b) {
268  return add(a, -b);
269  }
270 
271  template <size_t N>
272  inline Matrix<N> operator + (const Matrix<N> a, const Matrix<N>& b) {
273  return add(a, b);
274  }
275 
276  template <size_t N>
277  inline Matrix<N> operator - (const Matrix<N> a, const Matrix<N>& b) {
278  return subtract(a, b);
279  }
280 
281  template <size_t N>
282  inline Matrix<N> multiply(const double a, const Matrix<N>& m) {
283  Matrix<N> rtn;
284  rtn._matrix = a * m._matrix;
285  return rtn;
286  }
287 
288  template <size_t N>
289  inline Matrix<N> multiply(const Matrix<N>& m, const double a) {
290  return multiply(a, m);
291  }
292 
293  template <size_t N>
294  inline Matrix<N> divide(const Matrix<N>& m, const double a) {
295  return multiply(1/a, m);
296  }
297 
298  template <size_t N>
299  inline Matrix<N> operator * (const double a, const Matrix<N>& m) {
300  return multiply(a, m);
301  }
302 
303  template <size_t N>
304  inline Matrix<N> operator * (const Matrix<N>& m, const double a) {
305  return multiply(a, m);
306  }
307 
308  template <size_t N>
309  inline Matrix<N> multiply(const Matrix<N>& a, const Matrix<N>& b) {
310  Matrix<N> tmp;
311  tmp._matrix = a._matrix * b._matrix;
312  return tmp;
313  }
314 
315  template <size_t N>
316  inline Matrix<N> operator * (const Matrix<N>& a, const Matrix<N>& b) {
317  return multiply(a, b);
318  }
319 
320 
321  template <size_t N>
322  inline Vector<N> multiply(const Matrix<N>& a, const Vector<N>& b) {
323  Vector<N> tmp;
324  tmp._vec = a._matrix * b._vec;
325  return tmp;
326  }
327 
328  template <size_t N>
329  inline Vector<N> operator * (const Matrix<N>& a, const Vector<N>& b) {
330  return multiply(a, b);
331  }
332 
333  template <size_t N>
334  inline Matrix<N> transpose(const Matrix<N>& m) {
335  // Matrix<N> tmp;
336  // for (size_t i = 0; i < N; ++i) {
337  // for (size_t j = 0; j < N; ++j) {
338  // tmp.set(i, j, m.get(j, i));
339  // }
340  // }
341  // return tmp;
342  return m.transpose();
343  }
344 
345  template <size_t N>
346  inline Matrix<N> inverse(const Matrix<N>& m) {
347  return m.inverse();
348  }
349 
350  template <size_t N>
351  inline double det(const Matrix<N>& m) {
352  return m.determinant();
353  }
354 
355  template <size_t N>
356  inline double trace(const Matrix<N>& m) {
357  return m.trace();
358  }
359 
360 
362 
363 
365  template <size_t N>
366  inline string toString(const Matrix<N>& m) {
367  std::ostringstream ss;
368  ss << "[ ";
369  for (size_t i = 0; i < m.size(); ++i) {
370  ss << "( ";
371  for (size_t j = 0; j < m.size(); ++j) {
372  const double e = m.get(i, j);
373  ss << (Rivet::isZero(e) ? 0.0 : e) << " ";
374  }
375  ss << ") ";
376  }
377  ss << "]";
378  return ss.str();
379  }
380 
381 
383  template <size_t N>
384  inline std::ostream& operator << (std::ostream& out, const Matrix<N>& m) {
385  out << toString(m);
386  return out;
387  }
388 
389 
391 
392 
394  template <size_t N>
395  inline bool fuzzyEquals(const Matrix<N>& ma, const Matrix<N>& mb, double tolerance=1E-5) {
396  for (size_t i = 0; i < N; ++i) {
397  for (size_t j = 0; j < N; ++j) {
398  const double a = ma.get(i, j);
399  const double b = mb.get(i, j);
400  if (!Rivet::fuzzyEquals(a, b, tolerance)) return false;
401  }
402  }
403  return true;
404  }
405 
406 
408  template <size_t N>
409  inline bool isZero(const Matrix<N>& m, double tolerance=1E-5) {
410  return m.isZero(tolerance);
411  }
412 
413 
414 }
415 
416 #endif
Definition: MC_Cent_pPb.hh:10
Matrix< N > inverse() const
Calculate inverse.
Definition: MatrixN.hh:130
bool isSymm() const
Check for symmetry under transposition.
Definition: MatrixN.hh:184
double det() const
Calculate determinant.
Definition: MatrixN.hh:137
Vector< N > & set(const size_t index, const double value)
Set indexed value.
Definition: VectorN.hh:60
bool isZero(double tolerance=1E-5) const
Index-wise check for nullness, allowing for numerical precision.
Definition: MatrixN.hh:164
General -dimensional mathematical matrix object.
Definition: MatrixN.hh:14
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&(std::is_floating_point< N1 >::value||std::is_floating_point< N2 >::value), bool >::type fuzzyEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two numbers for equality with a degree of fuzziness.
Definition: MathUtils.hh:57
A minimal base class for -dimensional vectors.
Definition: VectorN.hh:13
double trace() const
Calculate trace.
Definition: MatrixN.hh:142
std::string toString(const AnalysisInfo &ai)
String representation.
Matrix< N > operator-() const
Negate.
Definition: MatrixN.hh:152
std::enable_if< std::is_floating_point< NUM >::value, bool >::type isZero(NUM val, double tolerance=1e-8)
Compare a number to zero.
Definition: MathUtils.hh:24
bool isEqual(Matrix< N > other) const
Check for index-wise equality, allowing for numerical precision.
Definition: MatrixN.hh:174
constexpr size_t size() const
Get dimensionality.
Definition: MatrixN.hh:159
bool isDiag() const
Check that all off-diagonal elements are zero, allowing for numerical precision.
Definition: MatrixN.hh:189