CbmRoot
Loading...
Searching...
No Matches
KfMatrixSym.h
Go to the documentation of this file.
1/* Copyright (C) 2007-2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergey Gorbunov [committer] */
4
5
10
11#ifndef KF_UTILS_KfMatrixSym_h
12#define KF_UTILS_KfMatrixSym_h 1
13
14#include "KfDefs.h"
15#include "KfMath.h"
16#include "KfUtils.h"
17
18#include <boost/serialization/access.hpp>
19
20#include <iomanip>
21#include <sstream>
22#include <string>
23
24#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA
25#include <Rtypes.h> // for ClassDef
26#endif
27
28namespace cbm::algo::kf
29{
30
35 template<typename T, int N>
36 class MatrixSym : public std::array<T, N*(N + 1) / 2> {
37 public:
38 static constexpr int kDimension{N};
39 static constexpr int kNofElements{(N) * (N + 1) / 2};
40
42 MatrixSym() { this->fill(0.); }
43
45 ~MatrixSym() = default;
46
51 T operator()(int i, int j) const { return (*this)[math::SymIndex(i, j)]; }
52
57 template<int i, int j>
59 {
60 return (*this)[math::SymIndex(i, j)];
61 }
62
67 T& operator()(int i, int j) { return (*this)[math::SymIndex(i, j)]; }
68
69
74 template<int i, int j>
76 {
77 return (*this)[math::SymIndex(i, j)];
78 }
79
82
84 template<typename... Args>
85 void Reset(Args... args)
86 {
87 static_assert(sizeof...(args) == kDimension,
88 "MatrixSym::Reset: number of arguments does not match matrix dimension ");
89 this->fill(0.);
90 SetDiagonal<0>(args...);
91 }
92
95 std::string ToString(int iv = -1) const;
96
99 std::string ToStringCorrelations(int iv = -1) const;
100
102 bool IsFinite() const { return IsFinite<DoPrintDebug::N>(nullptr); }
103
105 bool IsSimdEntryConsistent(int iv) const { return IsSimdEntryConsistent<DoPrintDebug::N>(nullptr, iv); }
106
109 bool IsConsistent(int nSimdFilled = -1) const { return IsConsistent<DoPrintDebug::N>(nullptr, nSimdFilled); }
110
112 template<DoPrintDebug FlagPrintDebug = DoPrintDebug::Y>
113 bool IsFinite(std::stringstream* ss) const;
114
116 template<DoPrintDebug FlagPrintDebug = DoPrintDebug::Y>
117 bool IsSimdEntryConsistent(std::stringstream* ss, int iv) const;
118
122 template<DoPrintDebug FlagPrintDebug = DoPrintDebug::Y>
123 bool IsConsistent(std::stringstream* ss, int nSimdFilled = -1) const;
124
128 template<class Archive>
129 void serialize(Archive& ar, const unsigned int /*version*/)
130 {
131 const std::array<T, kNofElements>& self = *this;
132 ar& self;
133 }
134
135 private:
137 template<int index, typename... Args>
138 void SetDiagonal(T val, Args... args)
139 {
140 if constexpr (index < kDimension) {
141 (*this)(Tag<index, index>{}) = val;
142 }
143 if constexpr (index < kDimension - 1) {
144 SetDiagonal<index + 1>(args...);
145 }
146 }
147
148#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA
149 // ClassDefNV(MatrixSym, 1);
150#endif
151 }; // class MatrixSym
152
153
154 template<int N>
156
157 template<int N>
159
160 template<int N>
162
163
166
167 template<typename T, int N>
168 inline std::string MatrixSym<T, N>::ToString(int iv) const
169 {
170 std::stringstream s;
171 s.setf(std::ios::scientific, std::ios::floatfield);
172 s << std::setprecision(6);
173
174 if constexpr (std::is_same_v<T, fvec>) {
175 // SIMD vector type
176 if (iv >= 0) {
177 // print only one component of the SIMD vector
178 for (int i = 0; i < kDimension; i++) {
179 for (int j = 0; j <= i; j++) {
180 s << " " << operator()(i, j)[iv];
181 }
182 s << std::endl;
183 }
184 }
185 else {
186 // print all components of the SIMD vector
187 for (unsigned int ivec = 0; ivec < fvec::Size; ++ivec) {
188 s << "Vector component " << ivec << ":" << std::endl;
189 s << ToString(ivec);
190 }
191 }
192 }
193 else {
194 // scalar data type
195 for (int i = 0; i < kDimension; i++) {
196 for (int j = 0; j <= i; j++) {
197 s << " " << operator()(i, j);
198 }
199 s << std::endl;
200 }
201 }
202 return s.str();
203 }
204
205
206 template<typename T, int N>
207 inline std::string MatrixSym<T, N>::ToStringCorrelations(int iv) const
208 {
209 std::stringstream s;
210 s.setf(std::ios::scientific, std::ios::floatfield);
211 s << std::setprecision(6);
212
213 if constexpr (std::is_same_v<T, fvec>) {
214 // SIMD vector type
215 if (iv >= 0) {
216 // print only one component of the SIMD vector
217 for (int i = 0; i < kDimension; i++) {
218 double sigi = sqrt(operator()(i, i)[iv]);
219 for (int j = 0; j < i; j++) {
220 double sigj = sqrt(operator()(j, j)[iv]);
221 double cij = operator()(i, j)[iv];
222 double corr = cij / (sigi * sigj);
223 s << " " << corr;
224 }
225 s << " " << sigi << std::endl;
226 }
227 }
228 else {
229 // print all components of the SIMD vector
230 for (unsigned int ivec = 0; ivec < fvec::Size; ++ivec) {
231 s << "Vector component " << ivec << ":" << std::endl;
232 s << ToStringCorrelations(ivec);
233 }
234 }
235 }
236 else {
237 // scalar data type
238 for (int i = 0; i < kDimension; i++) {
239 double sigi = sqrt(operator()(i, i));
240 for (int j = 0; j < i; j++) {
241 double sigj = sqrt(operator()(j, j));
242 double cij = operator()(i, j);
243 double corr = cij / (sigi * sigj);
244 s << " " << corr;
245 }
246 s << " " << sigi << std::endl;
247 }
248 }
249 return s.str();
250 }
251
252
253 template<typename T, int N>
254 template<DoPrintDebug FlagPrintDebug>
255 inline bool MatrixSym<T, N>::IsFinite(std::stringstream* ss) const
256 {
257 // verify that all the numbers in the object are valid floats
258 bool ret = true;
259
260 for (int i = 0; i < kDimension; i++) {
261 for (int j = 0; j <= i; j++) {
262 T val = this->operator()(i, j);
263 if (!utils::IsFinite(val)) {
264 ret = false;
265 if constexpr (FlagPrintDebug == DoPrintDebug::Y) {
266 if (ss) {
267 (*ss) << " Cov matrix element (" << i << "," << j << ") is undefined: " << val << std::endl;
268 }
269 }
270 }
271 }
272 }
273 return ret;
274 }
275
276
277 template<typename T, int N>
278 template<DoPrintDebug FlagPrintDebug>
279 inline bool MatrixSym<T, N>::IsSimdEntryConsistent(std::stringstream* ss, int iv) const
280 {
281 // verify that all the numbers in the object are valid floats
282
283 bool ok = IsFinite<FlagPrintDebug>(ss);
284 // verify diagonal elements.
285 // Cii is a squared dispersion of i-th parameter, it must be positive
286
287 for (int i = 0; i < kDimension; i++) {
288 double val = utils::simd::GetSimdEntry(this->operator()(i, i), iv);
289 if (val <= 0.) {
290 ok = false;
291 if constexpr (FlagPrintDebug == DoPrintDebug::Y) {
292 if (ss) {
293 (*ss) << " C[" << i << "," << i << "] is not positive: " << val << std::endl;
294 }
295 }
296 }
297 }
298
299 // verify non-diagonal elements.
300 // Cij/sqrt(Cii*Cjj) is a correlation between i-th and j-th parameter,
301 // it must belong to [-1,1]
302
303 for (int i = 1; i < kDimension; i++) {
304 for (int j = 0; j < i; j++) {
305 double tolerance = 1.0;
306 double cij = utils::simd::GetSimdEntry(this->operator()(i, j), iv);
307 double cii = utils::simd::GetSimdEntry(this->operator()(i, i), iv);
308 double cjj = utils::simd::GetSimdEntry(this->operator()(j, j), iv);
309 if (cij * cij > tolerance * (cii * cjj)) {
310 ok = false;
311 if constexpr (FlagPrintDebug == DoPrintDebug::Y) {
312 if (ss) {
313 (*ss) << " Correlation [" << i << "," << j << "] is too large: " << cij / sqrt(cii * cjj) << std::endl;
314 }
315 }
316 }
317 }
318 }
319
320 // verify triplets of correlations
321 // Kxy * Kxy + Kxz * Kxz + Kyz * Kyz <= 1 + 2 * Kxy * Kxz * Kyz
322
323 for (int i = 2; i < kDimension; i++) {
324 for (int j = 1; j < i; j++) {
325 for (int m = 0; m < j; m++) {
326 double tolerance = 1.0;
327 double Cxx = utils::simd::GetSimdEntry(this->operator()(i, i), iv);
328 double Cyy = utils::simd::GetSimdEntry(this->operator()(j, j), iv);
329 double Czz = utils::simd::GetSimdEntry(this->operator()(m, m), iv);
330 double Cxy = utils::simd::GetSimdEntry(this->operator()(i, j), iv);
331 double Cxz = utils::simd::GetSimdEntry(this->operator()(i, m), iv);
332 double Cyz = utils::simd::GetSimdEntry(this->operator()(j, m), iv);
333 if (Cxx * Cyz * Cyz + Cyy * Cxz * Cxz + Czz * Cxy * Cxy
334 > tolerance * (Cxx * Cyy * Czz + 2. * Cxy * Cyz * Cxz)) {
335 ok = false;
336 if constexpr (FlagPrintDebug == DoPrintDebug::Y) {
337 double Kxy = Cxy / sqrt(Cxx * Cyy);
338 double Kxz = Cxz / sqrt(Cxx * Czz);
339 double Kyz = Cyz / sqrt(Cyy * Czz);
340 if (ss) {
341 (*ss) << " Correlations between parameters " << i << ", " << j << ", " << m << " are wrong: " << Kxy
342 << " " << Kxz << " " << Kyz << std::endl
343 << " inequation: " << Kxy * Kxy + Kxz * Kxz + Kyz * Kyz << " > " << 1 + 2 * Kxy * Kxz * Kyz
344 << std::endl;
345 }
346 }
347 }
348 }
349 }
350 }
351
352 if constexpr (FlagPrintDebug == DoPrintDebug::Y) {
353 if (!ok) {
354 if (ss) {
355 (*ss) << "Matrix elements are not consistent: " << std::endl << std::endl;
356 (*ss) << ToString() << std::endl;
357 }
358 }
359 }
360 return ok;
361 } // IsSimdEntryConsistent
362
363
364 template<typename T, int N>
365 template<DoPrintDebug FlagPrintDebug>
366 inline bool MatrixSym<T, N>::IsConsistent(std::stringstream* ss, int nSimdFilled) const
367 {
368 int size = 1;
369
370 if constexpr (std::is_same_v<T, fvec>) {
371 size = fvec::size();
372 }
373
374 assert(nSimdFilled <= size);
375 if (nSimdFilled < 0) {
376 nSimdFilled = size;
377 }
378
379 bool ok = true;
380 for (int i = 0; i < nSimdFilled; ++i) {
382 }
383
384 if constexpr (FlagPrintDebug == DoPrintDebug::Y) {
385 if (!ok) {
386 if (ss) {
387 (*ss) << "MatrixSym parameters are not consistent: " << std::endl << std::endl;
388 if (nSimdFilled == size) {
389 (*ss) << " All vector elements are filled " << std::endl << std::endl;
390 }
391 else {
392 (*ss) << " Only first " << nSimdFilled << " vector elements are filled " << std::endl << std::endl;
393 }
394 (*ss) << ToString(-1) << std::endl;
395 }
396 }
397 }
398 return ok;
399 }
400
401} // namespace cbm::algo::kf
402
403
404#endif
std::string ToString(CbmCutId id)
Convert CbmCutId to a string representation.
Definition CbmCutId.cxx:7
Common constant definitions for the Kalman Filter library.
Collection of generic mathematical methods.
friend fvec sqrt(const fvec &a)
static constexpr size_t size()
Definition KfSimdPseudo.h:2
The class describes a symmetric N x N matrix stored in a low-triangular way.
Definition KfMatrixSym.h:36
~MatrixSym()=default
Default destructor.
T & operator()(Tag< i, j >)
Get matrix element, ensuring that indices are known at compile time.
Definition KfMatrixSym.h:75
bool IsConsistent(int nSimdFilled=-1) const
Checks whether the covariance matrix elements are consistent.
T operator()(Tag< i, j >) const
Get matrix element, ensuring that indices are known at compile time.
Definition KfMatrixSym.h:58
std::string ToString(int iv=-1) const
Prints parameters to a string.
MatrixSym()
default constructor
Definition KfMatrixSym.h:42
T & operator()(int i, int j)
Get matrix element, indices can be runtime values.
Definition KfMatrixSym.h:67
T operator()(int i, int j) const
Get matrix element, indices can be runtime values.
Definition KfMatrixSym.h:51
bool IsSimdEntryConsistent(int iv) const
Checks whether SIMD entry iv is consistent.
void SetDiagonal(T val, Args... args)
Helper method to set diagonal elements recursively.
bool IsFinite(std::stringstream *ss) const
Checks whether some parameters are finite.
std::string ToStringCorrelations(int iv=-1) const
Prints correlations to a string (assuming the matrix is a covariance matrix)
void serialize(Archive &ar, const unsigned int)
bool IsSimdEntryConsistent(std::stringstream *ss, int iv) const
Checks whether SIMD entry iv is consistent.
bool IsFinite() const
Checks whether some parameters are finite.
bool IsConsistent(std::stringstream *ss, int nSimdFilled=-1) const
Checks whether the covariance matrix elements are consistent.
void Reset(Args... args)
Resets to 0, diagonal elements to given values.
Definition KfMatrixSym.h:85
static constexpr size_t size()
constexpr int SymIndex(int i, int j)
Get matrix element for a symmetrix matrix stored in a low-triangular array.
Definition KfMath.h:21
double GetSimdEntry(DataT v, int k)
Definition KfUtils.h:356
bool IsFinite(const T &val)
Checks whether a variable of a particular type is finite.
Definition KfUtils.h:100
MatrixSym< fscal, N > MatrixSymS
@ Y
Print debug information.
Definition KfDefs.h:140
MatrixSym< double, N > MatrixSymD
@ N
Do not fit the time component.
Definition KfDefs.h:133
MatrixSym< float, N > MatrixSymF
A generic tag for tag dispatching.
Definition KfDefs.h:28