File indexing completed on 2025-01-18 10:10:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef ROOT_Minuit2_LASymMatrix
0011 #define ROOT_Minuit2_LASymMatrix
0012
0013 #include "Minuit2/MnConfig.h"
0014 #include "Minuit2/ABSum.h"
0015 #include "Minuit2/VectorOuterProduct.h"
0016 #include "Minuit2/MatrixInverse.h"
0017 #include "Minuit2/StackAllocator.h"
0018
0019 #include <cassert>
0020 #include <memory>
0021 #include <cstring> // for memcopy
0022
0023
0024
0025 namespace ROOT {
0026
0027 namespace Minuit2 {
0028
0029 int Mndaxpy(unsigned int, double, const double *, int, double *, int);
0030 int Mndscal(unsigned int, double, double *, int);
0031
0032 class LAVector;
0033
0034 int Invert(LASymMatrix &);
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 class LASymMatrix {
0046
0047 private:
0048 LASymMatrix() : fSize(0), fNRow(0), fData(nullptr) {}
0049
0050 public:
0051 typedef sym Type;
0052
0053 LASymMatrix(unsigned int n)
0054 : fSize(n * (n + 1) / 2),
0055 fNRow(n),
0056 fData( (n> 0) ? (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * n * (n + 1) / 2)
0057 : nullptr )
0058 {
0059
0060 if (fData)
0061 std::memset(fData, 0, fSize * sizeof(double));
0062 }
0063
0064 ~LASymMatrix()
0065 {
0066 if (fData)
0067 StackAllocatorHolder::Get().Deallocate(fData);
0068 }
0069
0070 LASymMatrix(const LASymMatrix &v)
0071 : fSize(v.size()), fNRow(v.Nrow()),
0072 fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.size()))
0073 {
0074 std::memcpy(fData, v.Data(), fSize * sizeof(double));
0075 }
0076
0077 LASymMatrix &operator=(const LASymMatrix &v)
0078 {
0079 if (fSize < v.size()) {
0080 if (fData)
0081 StackAllocatorHolder::Get().Deallocate(fData);
0082 fSize = v.size();
0083 fNRow = v.Nrow();
0084 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
0085 }
0086 std::memcpy(fData, v.Data(), fSize * sizeof(double));
0087 return *this;
0088 }
0089
0090 template <class T>
0091 LASymMatrix(const ABObj<sym, LASymMatrix, T> &v)
0092 : fSize(v.Obj().size()), fNRow(v.Obj().Nrow()),
0093 fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * v.Obj().size()))
0094 {
0095
0096
0097 std::memcpy(fData, v.Obj().Data(), fSize * sizeof(double));
0098 Mndscal(fSize, double(v.f()), fData, 1);
0099
0100 }
0101
0102 template <class A, class B, class T>
0103 LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, A, T>, ABObj<sym, B, T>>, T> &sum) : fSize(0), fNRow(0), fData(nullptr)
0104 {
0105
0106
0107 (*this) = sum.Obj().A();
0108 (*this) += sum.Obj().B();
0109
0110 }
0111
0112 template <class A, class T>
0113 LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, LASymMatrix, T>, ABObj<sym, A, T>>, T> &sum)
0114 : fSize(0), fNRow(0), fData(nullptr)
0115 {
0116
0117
0118
0119
0120
0121 (*this) = sum.Obj().B();
0122
0123 (*this) += sum.Obj().A();
0124
0125
0126 }
0127
0128 template <class A, class T>
0129 LASymMatrix(const ABObj<sym, ABObj<sym, A, T>, T> &something) : fSize(0), fNRow(0), fData(nullptr)
0130 {
0131
0132
0133 (*this) = something.Obj();
0134 (*this) *= something.f();
0135
0136
0137 }
0138
0139 template <class T>
0140 LASymMatrix(const ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T> &inv)
0141 : fSize(inv.Obj().Obj().Obj().size()), fNRow(inv.Obj().Obj().Obj().Nrow()),
0142 fData((double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * inv.Obj().Obj().Obj().size()))
0143 {
0144 std::memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize * sizeof(double));
0145 Mndscal(fSize, double(inv.Obj().Obj().f()), fData, 1);
0146 Invert(*this);
0147 Mndscal(fSize, double(inv.f()), fData, 1);
0148 }
0149
0150 template <class A, class T>
0151 LASymMatrix(
0152 const ABObj<sym, ABSum<ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T>, ABObj<sym, A, T>>, T>
0153 &sum)
0154 : fSize(0), fNRow(0), fData(nullptr)
0155 {
0156
0157
0158
0159
0160 (*this) = sum.Obj().B();
0161 (*this) += sum.Obj().A();
0162
0163
0164 }
0165
0166 LASymMatrix(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, double>, double>, double> &);
0167
0168 template <class A, class T>
0169 LASymMatrix(
0170 const ABObj<sym, ABSum<ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, T>, T>, T>, ABObj<sym, A, T>>, T> &sum)
0171 : fSize(0), fNRow(0), fData(nullptr)
0172 {
0173
0174
0175
0176
0177 (*this) = sum.Obj().B();
0178 (*this) += sum.Obj().A();
0179
0180
0181 }
0182
0183 LASymMatrix &operator+=(const LASymMatrix &m)
0184 {
0185
0186 assert(fSize == m.size());
0187 Mndaxpy(fSize, 1., m.Data(), 1, fData, 1);
0188 return *this;
0189 }
0190
0191 LASymMatrix &operator-=(const LASymMatrix &m)
0192 {
0193
0194 assert(fSize == m.size());
0195 Mndaxpy(fSize, -1., m.Data(), 1, fData, 1);
0196 return *this;
0197 }
0198
0199 template <class T>
0200 LASymMatrix &operator+=(const ABObj<sym, LASymMatrix, T> &m)
0201 {
0202
0203 assert(fSize == m.Obj().size());
0204 if (m.Obj().Data() == fData) {
0205 Mndscal(fSize, 1. + double(m.f()), fData, 1);
0206 } else {
0207 Mndaxpy(fSize, double(m.f()), m.Obj().Data(), 1, fData, 1);
0208 }
0209
0210 return *this;
0211 }
0212
0213 template <class A, class T>
0214 LASymMatrix &operator+=(const ABObj<sym, A, T> &m)
0215 {
0216
0217 (*this) += LASymMatrix(m);
0218 return *this;
0219 }
0220
0221 template <class T>
0222 LASymMatrix &operator+=(const ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T> &m)
0223 {
0224
0225
0226 assert(fNRow > 0);
0227 LASymMatrix tmp(m.Obj().Obj());
0228 Invert(tmp);
0229 tmp *= double(m.f());
0230 (*this) += tmp;
0231 return *this;
0232 }
0233
0234 template <class T>
0235 LASymMatrix &operator+=(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, T>, T>, T> &m)
0236 {
0237
0238
0239 assert(fNRow > 0);
0240 Outer_prod(*this, m.Obj().Obj().Obj(), m.f() * m.Obj().Obj().f() * m.Obj().Obj().f());
0241 return *this;
0242 }
0243
0244 LASymMatrix &operator*=(double scal)
0245 {
0246 Mndscal(fSize, scal, fData, 1);
0247 return *this;
0248 }
0249
0250 double operator()(unsigned int row, unsigned int col) const
0251 {
0252 assert(row < fNRow && col < fNRow);
0253 if (row > col)
0254 return fData[col + row * (row + 1) / 2];
0255 else
0256 return fData[row + col * (col + 1) / 2];
0257 }
0258
0259 double &operator()(unsigned int row, unsigned int col)
0260 {
0261 assert(row < fNRow && col < fNRow);
0262 if (row > col)
0263 return fData[col + row * (row + 1) / 2];
0264 else
0265 return fData[row + col * (col + 1) / 2];
0266 }
0267
0268 const double *Data() const { return fData; }
0269
0270 double *Data() { return fData; }
0271
0272 unsigned int size() const { return fSize; }
0273
0274 unsigned int Nrow() const { return fNRow; }
0275
0276 unsigned int Ncol() const { return Nrow(); }
0277
0278 private:
0279 unsigned int fSize;
0280 unsigned int fNRow;
0281 double *fData;
0282
0283 public:
0284 template <class T>
0285 LASymMatrix &operator=(const ABObj<sym, LASymMatrix, T> &v)
0286 {
0287
0288 if (fSize == 0 && !fData) {
0289 fSize = v.Obj().size();
0290 fNRow = v.Obj().Nrow();
0291 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
0292 } else {
0293 assert(fSize == v.Obj().size());
0294 }
0295
0296 std::memcpy(fData, v.Obj().Data(), fSize * sizeof(double));
0297 (*this) *= v.f();
0298 return *this;
0299 }
0300
0301 template <class A, class T>
0302 LASymMatrix &operator=(const ABObj<sym, ABObj<sym, A, T>, T> &something)
0303 {
0304
0305
0306 if (fSize == 0 && fData == nullptr) {
0307 (*this) = something.Obj();
0308 (*this) *= something.f();
0309 } else {
0310 LASymMatrix tmp(something.Obj());
0311 tmp *= something.f();
0312 assert(fSize == tmp.size());
0313 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
0314 }
0315
0316
0317 return *this;
0318 }
0319
0320 template <class A, class B, class T>
0321 LASymMatrix &operator=(const ABObj<sym, ABSum<ABObj<sym, A, T>, ABObj<sym, B, T>>, T> &sum)
0322 {
0323
0324
0325
0326 if (fSize == 0 && fData == nullptr) {
0327 (*this) = sum.Obj().A();
0328 (*this) += sum.Obj().B();
0329 (*this) *= sum.f();
0330 } else {
0331 LASymMatrix tmp(sum.Obj().A());
0332 tmp += sum.Obj().B();
0333 tmp *= sum.f();
0334 assert(fSize == tmp.size());
0335 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
0336 }
0337 return *this;
0338 }
0339
0340 template <class A, class T>
0341 LASymMatrix &operator=(const ABObj<sym, ABSum<ABObj<sym, LASymMatrix, T>, ABObj<sym, A, T>>, T> &sum)
0342 {
0343
0344
0345
0346 if (fSize == 0 && fData == nullptr) {
0347
0348 (*this) = sum.Obj().B();
0349 (*this) += sum.Obj().A();
0350 (*this) *= sum.f();
0351 } else {
0352
0353 LASymMatrix tmp(sum.Obj().B());
0354 tmp += sum.Obj().A();
0355 tmp *= sum.f();
0356 assert(fSize == tmp.size());
0357 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
0358 }
0359
0360 return *this;
0361 }
0362
0363 template <class T>
0364 LASymMatrix &operator=(const ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T> &inv)
0365 {
0366 if (fSize == 0 && fData == nullptr) {
0367 fSize = inv.Obj().Obj().Obj().size();
0368 fNRow = inv.Obj().Obj().Obj().Nrow();
0369 fData = (double *)StackAllocatorHolder::Get().Allocate(sizeof(double) * fSize);
0370 std::memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize * sizeof(double));
0371 (*this) *= inv.Obj().Obj().f();
0372 Invert(*this);
0373 (*this) *= inv.f();
0374 } else {
0375 LASymMatrix tmp(inv.Obj().Obj());
0376 Invert(tmp);
0377 tmp *= double(inv.f());
0378 assert(fSize == tmp.size());
0379 std::memcpy(fData, tmp.Data(), fSize * sizeof(double));
0380 }
0381 return *this;
0382 }
0383
0384 LASymMatrix &operator=(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, double>, double>, double> &);
0385 };
0386
0387 }
0388
0389 }
0390
0391 #endif