SND@LHC Software
Loading...
Searching...
No Matches
genfit::tools Namespace Reference

Functions

void invertMatrix (const TMatrixDSym &mat, TMatrixDSym &inv, double *determinant=NULL)
 Invert a matrix, throwing an Exception when inversion fails. Optional calculation of determinant.
 
void invertMatrix (TMatrixDSym &mat, double *determinant=NULL)
 Same, replacing its argument.
 
bool transposedForwardSubstitution (const TMatrixD &R, TVectorD &b)
 Solves R^t x = b, replacing b with the solution for x. R is assumed to be upper diagonal.
 
bool transposedForwardSubstitution (const TMatrixD &R, TMatrixD &b, int nCol)
 Same, for a column of the matrix b.

 
bool transposedInvert (const TMatrixD &R, TMatrixD &inv)
 Inverts the transpose of the upper right matrix R into inv.

 
void QR (TMatrixD &A)
 Replaces A with an upper right matrix connected to A by an orthongonal transformation. I.e., it computes R from a QR decomposition of A = QR, replacing A.
 
void safeAverage (const TMatrixDSym &C1, const TMatrixDSym &C2, TMatrixDSym &result)
 This averages the covariance matrices C1, C2 in a numerically stable way by using matrix square roots. This code is in no way optimized so use with care if speed is a concern.
 

Function Documentation

◆ invertMatrix() [1/2]

void genfit::tools::invertMatrix ( const TMatrixDSym &  mat,
TMatrixDSym &  inv,
double *  determinant = NULL 
)

Invert a matrix, throwing an Exception when inversion fails. Optional calculation of determinant.

Definition at line 38 of file Tools.cc.

38 {
39 inv.ResizeTo(mat);
40
41 // check if numerical limits are reached (i.e at least one entry < 1E-100 and/or at least one entry > 1E100)
42 if (!(mat<1.E100) || !(mat>-1.E100)){
43 Exception e("Tools::invertMatrix() - cannot invert matrix, entries too big (>1e100)",
44 __LINE__,__FILE__);
45 e.setFatal();
46 throw e;
47 }
48 // do the trivial inversions for 1x1 and 2x2 matrices manually
49 if (mat.GetNrows() == 1){
50 if (determinant != NULL) *determinant = mat(0,0);
51 inv(0,0) = 1./mat(0,0);
52 return;
53 }
54
55 if (mat.GetNrows() == 2){
56 double det = mat(0,0)*mat(1,1) - mat(1,0)*mat(1,0);
57 if (determinant != NULL) *determinant = det;
58 if(fabs(det) < 1E-50){
59 Exception e("Tools::invertMatrix() - cannot invert matrix , determinant = 0",
60 __LINE__,__FILE__);
61 e.setFatal();
62 throw e;
63 }
64 det = 1./det;
65 inv(0,0) = det * mat(1,1);
66 inv(0,1) = inv(1,0) = -det * mat(1,0);
67 inv(1,1) = det * mat(0,0);
68 return;
69 }
70
71
72 if (useCramer && mat.GetNrows() <= 6){
73 Bool_t (*inversion)(TMatrixDSym&, Double_t*) = 0;
74 inv.ResizeTo(mat);
75 inv = mat;
76 switch (mat.GetNrows()) {
77 case 3:
78 inversion = TMatrixTSymCramerInv::Inv3x3; break;
79 case 4:
80 inversion = TMatrixTSymCramerInv::Inv4x4; break;
81 case 5:
82 inversion = TMatrixTSymCramerInv::Inv5x5; break;
83 case 6:
84 inversion = TMatrixTSymCramerInv::Inv6x6; break;
85 }
86
87 Bool_t success = inversion(inv, determinant);
88 if (!success){
89 Exception e("Tools::invertMatrix() - cannot invert matrix, determinant = 0",
90 __LINE__,__FILE__);
91 e.setFatal();
92 throw e;
93 }
94 return;
95 }
96
97 // else use TDecompChol
98 bool status = 0;
99 TDecompChol invertAlgo(mat, 1E-50);
100
101 status = invertAlgo.Invert(inv);
102 if(status == 0){
103 Exception e("Tools::invertMatrix() - cannot invert matrix, status = 0",
104 __LINE__,__FILE__);
105 e.setFatal();
106 throw e;
107 }
108
109 if (determinant != NULL) {
110 double d1, d2;
111 invertAlgo.Det(d1, d2);
112 *determinant = ldexp(d1, d2);
113 }
114}
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition Exception.h:48

◆ invertMatrix() [2/2]

void genfit::tools::invertMatrix ( TMatrixDSym &  mat,
double *  determinant = NULL 
)

Same, replacing its argument.

Definition at line 116 of file Tools.cc.

116 {
117 // check if numerical limits are reached (i.e at least one entry < 1E-100 and/or at least one entry > 1E100)
118 if (!(mat<1.E100) || !(mat>-1.E100)){
119 Exception e("Tools::invertMatrix() - cannot invert matrix, entries too big (>1e100)",
120 __LINE__,__FILE__);
121 e.setFatal();
122 throw e;
123 }
124 // do the trivial inversions for 1x1 and 2x2 matrices manually
125 if (mat.GetNrows() == 1){
126 if (determinant != NULL) *determinant = mat(0,0);
127 mat(0,0) = 1./mat(0,0);
128 return;
129 }
130
131 if (mat.GetNrows() == 2){
132 double *arr = mat.GetMatrixArray();
133 double det = arr[0]*arr[3] - arr[1]*arr[1];
134 if (determinant != NULL) *determinant = det;
135 if(fabs(det) < 1E-50){
136 Exception e("Tools::invertMatrix() - cannot invert matrix, determinant = 0",
137 __LINE__,__FILE__);
138 e.setFatal();
139 throw e;
140 }
141 det = 1./det;
142 double temp[3];
143 temp[0] = det * arr[3];
144 temp[1] = -det * arr[1];
145 temp[2] = det * arr[0];
146 //double *arr = mat.GetMatrixArray();
147 arr[0] = temp[0];
148 arr[1] = arr[2] = temp[1];
149 arr[3] = temp[2];
150 return;
151 }
152
153 if (useCramer && mat.GetNrows() <= 6){
154 Bool_t (*inversion)(TMatrixDSym&, Double_t*) = 0;
155 switch (mat.GetNrows()) {
156 case 3:
157 inversion = TMatrixTSymCramerInv::Inv3x3; break;
158 case 4:
159 inversion = TMatrixTSymCramerInv::Inv4x4; break;
160 case 5:
161 inversion = TMatrixTSymCramerInv::Inv5x5; break;
162 case 6:
163 inversion = TMatrixTSymCramerInv::Inv6x6; break;
164 }
165
166 Bool_t success = inversion(mat, determinant);
167 if (!success){
168 Exception e("Tools::invertMatrix() - cannot invert matrix, determinant = 0",
169 __LINE__,__FILE__);
170 e.setFatal();
171 throw e;
172 }
173 return;
174 }
175
176 // else use TDecompChol
177 bool status = 0;
178 TDecompChol invertAlgo(mat, 1E-50);
179
180 status = invertAlgo.Invert(mat);
181 if(status == 0){
182 Exception e("Tools::invertMatrix() - cannot invert matrix, status = 0",
183 __LINE__,__FILE__);
184 e.setFatal();
185 throw e;
186 }
187
188 if (determinant != NULL) {
189 double d1, d2;
190 invertAlgo.Det(d1, d2);
191 *determinant = ldexp(d1, d2);
192 }
193}

◆ QR()

void genfit::tools::QR ( TMatrixD &  A)

Replaces A with an upper right matrix connected to A by an orthongonal transformation. I.e., it computes R from a QR decomposition of A = QR, replacing A.

Definition at line 249 of file Tools.cc.

250{
251 int nCols = A.GetNcols();
252 int nRows = A.GetNrows();
253 assert(nRows >= nCols);
254 // This uses Businger and Golub's algorithm from Handbook for
255 // Automatical Computation, Vol. 2, Chapter 8, but without
256 // pivoting. I.e., we stop at the middle of page 112. We don't
257 // explicitly calculate the orthogonal matrix.
258
259 double *const ak = A.GetMatrixArray();
260 // No variable-length arrays in C++, alloca does the exact same thing ...
261 double *const u = (double *)alloca(sizeof(double)*nRows);
262
263 // Main loop over matrix columns.
264 for (int k = 0; k < nCols; ++k) {
265 double akk = ak[k*nCols + k];
266
267 double sum = akk*akk;
268 // Put together a housholder transformation.
269 for (int i = k + 1; i < nRows; ++i) {
270 sum += ak[i*nCols + k]*ak[i*nCols + k];
271 u[i] = ak[i*nCols + k];
272 }
273 double sigma = sqrt(sum);
274 double beta = 1/(sum + sigma*fabs(akk));
275 // The algorithm uses only the uk[i] for i >= k.
276 u[k] = copysign(sigma + fabs(akk), akk);
277
278 // Calculate y (again taking into account zero entries). This
279 // encodes how the (sub)matrix changes by the householder transformation.
280 for (int i = k; i < nCols; ++i) {
281 double y = 0;
282 for (int j = k; j < nRows; ++j)
283 y += u[j]*ak[j*nCols + i];
284 y *= beta;
285 // ... and apply the changes.
286 for (int j = k; j < nRows; ++j)
287 ak[j*nCols + i] -= u[j]*y; //y[j];
288 }
289 }
290
291 // Zero below diagonal
292 for (int i = 1; i < nCols; ++i)
293 for (int j = 0; j < i; ++j)
294 ak[i*nCols + j] = 0.;
295 for (int i = nCols; i < nRows; ++i)
296 for (int j = 0; j < nCols; ++j)
297 ak[i*nCols + j] = 0.;
298}
int i
Definition ShipAna.py:86

◆ safeAverage()

void genfit::tools::safeAverage ( const TMatrixDSym &  C1,
const TMatrixDSym &  C2,
TMatrixDSym &  result 
)

This averages the covariance matrices C1, C2 in a numerically stable way by using matrix square roots. This code is in no way optimized so use with care if speed is a concern.

Definition at line 303 of file Tools.cc.

305{
306 /*
307 The algorithm proceeds as follows:
308 write C1 = S1 S1' (prime for transpose),
309 C2 = S2 S2'
310 Then the inverse of the average can be written as ("." for matrix
311 multiplication)
312 C^-1 = ((S1'^-1, S2'^-1) . (S1'^-1) )
313 ( (S2'^-1) )
314 Inserting an orthogonal matrix T in the middle:
315 C^-1 = ((S1'^-1, S2'^-1) . T . T' . (S1'^-1) )
316 ( (S2'^-1) )
317 doesn't change this because T.T' = 1.
318 Now choose T s.t. T'.(S1'^-1, S2'^-1)' is an upper right matrix. We
319 use Tools::QR for the purpose, as we don't actually need T.
320
321 Then the inverse needed to obtain the covariance matrix can be
322 obtained by inverting the upper right matrix, which is squared to
323 obtained the new covariance matrix. */
324 TDecompChol dec1(C1);
325 dec1.Decompose();
326 TDecompChol dec2(C2);
327 dec2.Decompose();
328
329 const TMatrixD& S1 = dec1.GetU();
330 const TMatrixD& S2 = dec2.GetU();
331
332 TMatrixD S1inv, S2inv;
333 transposedInvert(S1, S1inv);
334 transposedInvert(S2, S2inv);
335
336 TMatrixD A(2 * S1.GetNrows(), S1.GetNcols());
337 for (int i = 0; i < S1.GetNrows(); ++i) {
338 for (int j = 0; j < S2.GetNcols(); ++j) {
339 A(i, j) = S1inv(i, j);
340 A(i + S1.GetNrows(), j) = S2inv(i, j);
341 }
342 }
343
344 QR(A);
345 A.ResizeTo(S1.GetNrows(), S1.GetNrows());
346
347 TMatrixD inv;
348 transposedInvert(A, inv);
349
350 result.ResizeTo(inv.GetNcols(), inv.GetNcols());
351 result = TMatrixDSym(TMatrixDSym::kAtA, inv);
352}
bool transposedInvert(const TMatrixD &R, TMatrixD &inv)
Inverts the transpose of the upper right matrix R into inv.
Definition Tools.cc:231

◆ transposedForwardSubstitution() [1/2]

bool genfit::tools::transposedForwardSubstitution ( const TMatrixD &  R,
TMatrixD &  b,
int  nCol 
)

Same, for a column of the matrix b.

Definition at line 215 of file Tools.cc.

216{
217 size_t n = R.GetNrows();
218 for (unsigned int i = 0; i < n; ++i) {
219 double sum = b(i, nCol);
220 for (unsigned int j = 0; j < i; ++j) {
221 sum -= b(j, nCol)*R(j,i); // already replaced previous elements in b.
222 }
223 if (R(i,i) == 0)
224 return false;
225 b(i, nCol) = sum / R(i,i);
226 }
227 return true;
228}

◆ transposedForwardSubstitution() [2/2]

bool genfit::tools::transposedForwardSubstitution ( const TMatrixD &  R,
TVectorD &  b 
)

Solves R^t x = b, replacing b with the solution for x. R is assumed to be upper diagonal.

Definition at line 199 of file Tools.cc.

200{
201 size_t n = R.GetNrows();
202 for (unsigned int i = 0; i < n; ++i) {
203 double sum = b(i);
204 for (unsigned int j = 0; j < i; ++j) {
205 sum -= b(j)*R(j,i); // already replaced previous elements in b.
206 }
207 if (R(i,i) == 0)
208 return false;
209 b(i) = sum / R(i,i);
210 }
211 return true;
212}

◆ transposedInvert()

bool genfit::tools::transposedInvert ( const TMatrixD &  R,
TMatrixD &  inv 
)

Inverts the transpose of the upper right matrix R into inv.

Definition at line 231 of file Tools.cc.

232{
233 bool result = true;
234
235 inv.ResizeTo(R);
236 for (int i = 0; i < inv.GetNrows(); ++i)
237 for (int j = 0; j < inv.GetNcols(); ++j)
238 inv(i, j) = (i == j);
239
240 for (int i = 0; i < inv.GetNcols(); ++i)
241 result = result && transposedForwardSubstitution(R, inv, i);
242
243 return result;
244}
bool transposedForwardSubstitution(const TMatrixD &R, TVectorD &b)
Solves R^t x = b, replacing b with the solution for x. R is assumed to be upper diagonal.
Definition Tools.cc:199