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