File indexing completed on 2025-08-05 08:18:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "Tools.h"
0021
0022 #include <cmath>
0023 #include <memory>
0024 #include <typeinfo>
0025 #include <cassert>
0026
0027 #include <TDecompChol.h>
0028 #include <TMatrixDSymEigen.h>
0029 #include <TMatrixTSymCramerInv.h>
0030 #include <TMath.h>
0031
0032 #include "AbsHMatrix.h"
0033 #include "Exception.h"
0034
0035
0036 namespace genfit {
0037
0038 void tools::invertMatrix(const TMatrixDSym& mat, TMatrixDSym& inv, double* determinant){
0039 inv.ResizeTo(mat);
0040
0041
0042 if (!(mat<1.E100) || !(mat>-1.E100)){
0043 Exception e("Tools::invertMatrix() - cannot invert matrix, entries too big (>1e100)",
0044 __LINE__,__FILE__);
0045 e.setFatal();
0046 throw e;
0047 }
0048
0049 if (mat.GetNrows() == 1){
0050 if (determinant != nullptr) *determinant = mat(0,0);
0051 inv(0,0) = 1./mat(0,0);
0052 return;
0053 }
0054
0055 if (mat.GetNrows() == 2){
0056 double det = mat(0,0)*mat(1,1) - mat(1,0)*mat(1,0);
0057 if (determinant != nullptr) *determinant = det;
0058 if(fabs(det) < 1E-50){
0059 Exception e("Tools::invertMatrix() - cannot invert matrix , determinant = 0",
0060 __LINE__,__FILE__);
0061 e.setFatal();
0062 throw e;
0063 }
0064 det = 1./det;
0065 inv(0,0) = det * mat(1,1);
0066 inv(0,1) = inv(1,0) = -det * mat(1,0);
0067 inv(1,1) = det * mat(0,0);
0068 return;
0069 }
0070
0071
0072 bool status = 0;
0073 TDecompChol invertAlgo(mat, 1E-50);
0074
0075 status = invertAlgo.Invert(inv);
0076 if(status == 0){
0077 Exception e("Tools::invertMatrix() - cannot invert matrix, status = 0",
0078 __LINE__,__FILE__);
0079 e.setFatal();
0080 throw e;
0081 }
0082
0083 if (determinant != nullptr) {
0084 double d1, d2;
0085 invertAlgo.Det(d1, d2);
0086 *determinant = ldexp(d1, d2);
0087 }
0088 }
0089
0090 void tools::invertMatrix(TMatrixDSym& mat, double* determinant){
0091
0092 if (!(mat<1.E100) || !(mat>-1.E100)){
0093 Exception e("Tools::invertMatrix() - cannot invert matrix, entries too big (>1e100)",
0094 __LINE__,__FILE__);
0095 e.setFatal();
0096 throw e;
0097 }
0098
0099 if (mat.GetNrows() == 1){
0100 if (determinant != nullptr) *determinant = mat(0,0);
0101 mat(0,0) = 1./mat(0,0);
0102 return;
0103 }
0104
0105 if (mat.GetNrows() == 2){
0106 double *arr = mat.GetMatrixArray();
0107 double det = arr[0]*arr[3] - arr[1]*arr[1];
0108 if (determinant != nullptr) *determinant = det;
0109 if(fabs(det) < 1E-50){
0110 Exception e("Tools::invertMatrix() - cannot invert matrix, determinant = 0",
0111 __LINE__,__FILE__);
0112 e.setFatal();
0113 throw e;
0114 }
0115 det = 1./det;
0116 double temp[3];
0117 temp[0] = det * arr[3];
0118 temp[1] = -det * arr[1];
0119 temp[2] = det * arr[0];
0120
0121 arr[0] = temp[0];
0122 arr[1] = arr[2] = temp[1];
0123 arr[3] = temp[2];
0124 return;
0125 }
0126
0127
0128 bool status = 0;
0129 TDecompChol invertAlgo(mat, 1E-50);
0130
0131 status = invertAlgo.Invert(mat);
0132 if(status == 0){
0133 Exception e("Tools::invertMatrix() - cannot invert matrix, status = 0",
0134 __LINE__,__FILE__);
0135 e.setFatal();
0136 throw e;
0137 }
0138
0139 if (determinant != nullptr) {
0140 double d1, d2;
0141 invertAlgo.Det(d1, d2);
0142 *determinant = ldexp(d1, d2);
0143 }
0144 }
0145
0146
0147
0148
0149
0150 bool tools::transposedForwardSubstitution(const TMatrixD& R, TVectorD& b)
0151 {
0152 size_t n = R.GetNrows();
0153 double *const bk = b.GetMatrixArray();
0154 const double *const Rk = R.GetMatrixArray();
0155 for (unsigned int i = 0; i < n; ++i) {
0156 double sum = bk[i];
0157 for (unsigned int j = 0; j < i; ++j) {
0158 sum -= bk[j]*Rk[j*n + i];
0159 }
0160 if (Rk[i*n+i] == 0)
0161 return false;
0162 bk[i] = sum / Rk[i*n + i];
0163 }
0164 return true;
0165 }
0166
0167
0168
0169
0170 bool tools::transposedForwardSubstitution(const TMatrixD& R, TMatrixD& b, int nCol)
0171 {
0172 size_t n = R.GetNrows();
0173 double *const bk = b.GetMatrixArray() + nCol;
0174 const double *const Rk = R.GetMatrixArray();
0175 for (unsigned int i = nCol; i < n; ++i) {
0176 double sum = (i == (size_t)nCol);
0177 for (unsigned int j = 0; j < i; ++j) {
0178 sum -= bk[j*n]*Rk[j*n + i];
0179 }
0180 if (Rk[i*n+i] == 0)
0181 return false;
0182 bk[i*n] = sum / Rk[i*n + i];
0183 }
0184 return true;
0185 }
0186
0187
0188
0189 bool tools::transposedInvert(const TMatrixD& R, TMatrixD& inv)
0190 {
0191 bool result = true;
0192
0193 inv.ResizeTo(R);
0194 double *const invk = inv.GetMatrixArray();
0195 int nRows = inv.GetNrows();
0196 for (int i = 0; i < nRows; ++i)
0197 for (int j = 0; j < nRows; ++j)
0198 invk[i*nRows + j] = (i == j);
0199
0200 for (int i = 0; i < inv.GetNcols(); ++i)
0201 result = result && transposedForwardSubstitution(R, inv, i);
0202
0203 return result;
0204 }
0205
0206
0207
0208
0209 void tools::QR(TMatrixD& A)
0210 {
0211 int nCols = A.GetNcols();
0212 int nRows = A.GetNrows();
0213 assert(nRows >= nCols);
0214
0215
0216
0217
0218
0219 double *const ak = A.GetMatrixArray();
0220
0221 double *const u = (double *)alloca(sizeof(double)*nRows);
0222
0223
0224 for (int k = 0; k < nCols; ++k) {
0225 double akk = ak[k*nCols + k];
0226
0227 double sum = akk*akk;
0228
0229 for (int i = k + 1; i < nRows; ++i) {
0230 sum += ak[i*nCols + k]*ak[i*nCols + k];
0231 u[i] = ak[i*nCols + k];
0232 }
0233 double sigma = sqrt(sum);
0234 double beta = 1/(sum + sigma*fabs(akk));
0235
0236 u[k] = copysign(sigma + fabs(akk), akk);
0237
0238
0239
0240 for (int i = k; i < nCols; ++i) {
0241 double y = 0;
0242 for (int j = k; j < nRows; ++j)
0243 y += u[j]*ak[j*nCols + i];
0244 y *= beta;
0245
0246 for (int j = k; j < nRows; ++j)
0247 ak[j*nCols + i] -= u[j]*y;
0248 }
0249 }
0250
0251
0252 for (int i = 1; i < nCols; ++i)
0253 for (int j = 0; j < i; ++j)
0254 ak[i*nCols + j] = 0.;
0255 for (int i = nCols; i < nRows; ++i)
0256 for (int j = 0; j < nCols; ++j)
0257 ak[i*nCols + j] = 0.;
0258 }
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 void tools::QR(TMatrixD& A, TVectorD& b)
0271 {
0272 int nCols = A.GetNcols();
0273 int nRows = A.GetNrows();
0274 assert(nRows >= nCols);
0275 assert(b.GetNrows() == nRows);
0276
0277
0278
0279
0280
0281
0282
0283 double *const ak = A.GetMatrixArray();
0284 double *const bk = b.GetMatrixArray();
0285
0286
0287 double u[500];
0288
0289
0290 for (int k = 0; k < nCols; ++k) {
0291 double akk = ak[k*nCols + k];
0292
0293 double sum = akk*akk;
0294
0295 for (int i = k + 1; i < nRows; ++i) {
0296 sum += ak[i*nCols + k]*ak[i*nCols + k];
0297 u[i] = ak[i*nCols + k];
0298 }
0299 double sigma = sqrt(sum);
0300 double beta = 1/(sum + sigma*fabs(akk));
0301
0302 u[k] = copysign(sigma + fabs(akk), akk);
0303
0304
0305
0306 double yb = 0;
0307 for (int j = k; j < nRows; ++j)
0308 yb += u[j]*bk[j];
0309 yb *= beta;
0310
0311 for (int j = k; j < nRows; ++j)
0312 bk[j] -= u[j]*yb;
0313
0314
0315
0316 for (int i = k; i < nCols; ++i) {
0317 double y = 0;
0318 for (int j = k; j < nRows; ++j)
0319 y += u[j]*ak[j*nCols + i];
0320 y *= beta;
0321
0322 for (int j = k; j < nRows; ++j)
0323 ak[j*nCols + i] -= u[j]*y;
0324 }
0325 }
0326
0327
0328 for (int i = 1; i < nCols; ++i)
0329 for (int j = 0; j < i; ++j)
0330 ak[i*nCols + j] = 0.;
0331 for (int i = nCols; i < nRows; ++i)
0332 for (int j = 0; j < nCols; ++j)
0333 ak[i*nCols + j] = 0.;
0334 }
0335
0336
0337 void
0338 tools::noiseMatrixSqrt(const TMatrixDSym& noise,
0339 TMatrixD& noiseSqrt)
0340 {
0341
0342
0343 TMatrixDSymEigen eig(noise);
0344 noiseSqrt.ResizeTo(noise);
0345 noiseSqrt = eig.GetEigenVectors();
0346 double* pNoiseSqrt = noiseSqrt.GetMatrixArray();
0347 const TVectorD& evs(eig.GetEigenValues());
0348 const double* pEvs = evs.GetMatrixArray();
0349
0350
0351
0352
0353 int iCol = 0;
0354 for (; iCol < noiseSqrt.GetNrows(); ++iCol) {
0355 double ev = pEvs[iCol] > 0 ? sqrt(pEvs[iCol]) : 0;
0356
0357
0358 for (int j = 0; j < noiseSqrt.GetNrows(); ++j) {
0359 pNoiseSqrt[j*noiseSqrt.GetNcols() + iCol] *= ev;
0360 }
0361 }
0362 if (iCol < noiseSqrt.GetNcols()) {
0363
0364 noiseSqrt.ResizeTo(noiseSqrt.GetNrows(), iCol);
0365 }
0366
0367
0368 }
0369
0370
0371
0372
0373
0374
0375
0376 void
0377 tools::kalmanPredictionCovSqrt(const TMatrixD& S,
0378 const TMatrixD& F, const TMatrixD& Q,
0379 TMatrixD& Snew)
0380 {
0381 Snew.ResizeTo(S.GetNrows() + Q.GetNcols(),
0382 S.GetNcols());
0383
0384
0385 Snew.SetSub(0, 0, TMatrixD(S, TMatrixD::kMultTranspose, F));
0386 if (Q.GetNcols() != 0)
0387 Snew.SetSub(S.GetNrows(), 0, TMatrixD(TMatrixD::kTransposed, Q));
0388
0389 tools::QR(Snew);
0390
0391
0392 Snew.ResizeTo(S.GetNrows(), S.GetNrows());
0393 }
0394
0395
0396
0397
0398
0399
0400
0401 void
0402 tools::kalmanUpdateSqrt(const TMatrixD& S,
0403 const TVectorD& res, const TMatrixD& R,
0404 const AbsHMatrix* H,
0405 TVectorD& update, TMatrixD& SNew)
0406 {
0407 TMatrixD pre(S.GetNrows() + R.GetNrows(),
0408 S.GetNcols() + R.GetNcols());
0409 pre.SetSub(0, 0, R);
0410 pre.SetSub(R.GetNrows(), 0, H->MHt(S)); pre.SetSub(R.GetNrows(), R.GetNcols(), S);
0411
0412 tools::QR(pre);
0413 const TMatrixD& r = pre;
0414
0415 const TMatrixD& a(r.GetSub(0, R.GetNrows()-1,
0416 0, R.GetNcols()-1));
0417 TMatrixD K(TMatrixD::kTransposed, r.GetSub(0, R.GetNrows()-1, R.GetNcols(), pre.GetNcols()-1));
0418 SNew = r.GetSub(R.GetNrows(), pre.GetNrows()-1, R.GetNcols(), pre.GetNcols()-1);
0419
0420 update.ResizeTo(res);
0421 update = res;
0422 tools::transposedForwardSubstitution(a, update);
0423 update *= K;
0424 }
0425
0426 }