rivet is hosted by Hepforge, IPPP Durham
Rivet 3.1.6
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
10namespace 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
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
General -dimensional mathematical matrix object.
Definition: MatrixN.hh:30
double trace() const
Calculate trace.
Definition: MatrixN.hh:142
double det() const
Calculate determinant.
Definition: MatrixN.hh:137
Matrix< N > operator-() const
Negate.
Definition: MatrixN.hh:152
bool isZero(double tolerance=1E-5) const
Index-wise check for nullness, allowing for numerical precision.
Definition: MatrixN.hh:164
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
Matrix< N > inverse() const
Calculate inverse.
Definition: MatrixN.hh:130
bool isSymm() const
Check for symmetry under transposition.
Definition: MatrixN.hh:184
bool isEqual(Matrix< N > other) const
Check for index-wise equality, allowing for numerical precision.
Definition: MatrixN.hh:174
A minimal base class for -dimensional vectors.
Definition: VectorN.hh:23
Vector< N > & set(const size_t index, const double value)
Set indexed value.
Definition: VectorN.hh:60
Definition: MC_Cent_pPb.hh:10
std::ostream & operator<<(std::ostream &os, const AnalysisInfo &ai)
Stream an AnalysisInfo as a text description.
Definition: AnalysisInfo.hh:362
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
std::string toString(const AnalysisInfo &ai)
String representation.
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