00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef ROOT_Minuit2_LASymMatrix
00011 #define ROOT_Minuit2_LASymMatrix
00012
00013 #include "Minuit2/MnConfig.h"
00014 #include "Minuit2/ABSum.h"
00015 #include "Minuit2/VectorOuterProduct.h"
00016 #include "Minuit2/MatrixInverse.h"
00017
00018 #include <cassert>
00019 #include <memory>
00020
00021
00022
00023
00024 #include "Minuit2/StackAllocator.h"
00025
00026
00027
00028 #include <string.h>
00029
00030 namespace ROOT {
00031
00032 namespace Minuit2 {
00033
00034
00035 int Mndaxpy(unsigned int, double, const double*, int, double*, int);
00036 int Mndscal(unsigned int, double, double*, int);
00037
00038 class LAVector;
00039
00040 int Invert ( LASymMatrix & );
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 class LASymMatrix {
00052
00053 private:
00054
00055 LASymMatrix() : fSize(0), fNRow(0), fData(0) {}
00056
00057 public:
00058
00059 typedef sym Type;
00060
00061 LASymMatrix(unsigned int n) : fSize(n*(n+1)/2), fNRow(n), fData((double*)StackAllocatorHolder::Get().Allocate(sizeof(double)*n*(n+1)/2)) {
00062
00063 memset(fData, 0, fSize*sizeof(double));
00064
00065 }
00066
00067 ~LASymMatrix() {
00068
00069
00070
00071
00072 if(fData) StackAllocatorHolder::Get().Deallocate(fData);
00073 }
00074
00075 LASymMatrix(const LASymMatrix& v) :
00076 fSize(v.size()), fNRow(v.Nrow()), fData((double*)StackAllocatorHolder::Get().Allocate(sizeof(double)*v.size())) {
00077
00078 memcpy(fData, v.Data(), fSize*sizeof(double));
00079 }
00080
00081 LASymMatrix& operator=(const LASymMatrix& v) {
00082
00083
00084
00085 assert(fSize == v.size());
00086 memcpy(fData, v.Data(), fSize*sizeof(double));
00087 return *this;
00088 }
00089
00090 template<class T>
00091 LASymMatrix(const ABObj<sym, LASymMatrix, T>& v) :
00092 fSize(v.Obj().size()), fNRow(v.Obj().Nrow()), fData((double*)StackAllocatorHolder::Get().Allocate(sizeof(double)*v.Obj().size())) {
00093
00094
00095 memcpy(fData, v.Obj().Data(), fSize*sizeof(double));
00096 Mndscal(fSize, double(v.f()), fData, 1);
00097
00098 }
00099
00100 template<class A, class B, class T>
00101 LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, A, T>, ABObj<sym, B, T> >,T>& sum) : fSize(0), fNRow(0), fData(0) {
00102
00103
00104 (*this) = sum.Obj().A();
00105 (*this) += sum.Obj().B();
00106
00107 }
00108
00109 template<class A, class T>
00110 LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, LASymMatrix, T>, ABObj<sym, A, T> >,T>& sum) : fSize(0), fNRow(0), fData(0) {
00111
00112
00113
00114
00115 (*this)=sum.Obj().B();
00116
00117 (*this)+=sum.Obj().A();
00118
00119 }
00120
00121 template<class A, class T>
00122 LASymMatrix(const ABObj<sym, ABObj<sym, A, T>, T>& something) : fSize(0), fNRow(0), fData(0) {
00123
00124 (*this) = something.Obj();
00125 (*this) *= something.f();
00126
00127 }
00128
00129 template<class T>
00130 LASymMatrix(const ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T>& inv) : fSize(inv.Obj().Obj().Obj().size()), fNRow(inv.Obj().Obj().Obj().Nrow()), fData((double*)StackAllocatorHolder::Get().Allocate(sizeof(double)*inv.Obj().Obj().Obj().size())) {
00131 memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize*sizeof(double));
00132 Mndscal(fSize, double(inv.Obj().Obj().f()), fData, 1);
00133 Invert(*this);
00134 Mndscal(fSize, double(inv.f()), fData, 1);
00135 }
00136
00137 template<class A, class T>
00138 LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T>, ABObj<sym, A, T> >, T>& sum) : fSize(0), fNRow(0), fData(0) {
00139
00140
00141
00142 (*this)=sum.Obj().B();
00143 (*this)+=sum.Obj().A();
00144
00145 }
00146
00147 LASymMatrix(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, double>, double>, double>&);
00148
00149 template<class A, class T>
00150 LASymMatrix(const ABObj<sym, ABSum<ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, T>, T>, T>, ABObj<sym, A, T> >, T>& sum) : fSize(0), fNRow(0), fData(0) {
00151
00152
00153
00154 (*this)=sum.Obj().B();
00155 (*this)+=sum.Obj().A();
00156
00157 }
00158
00159 LASymMatrix& operator+=(const LASymMatrix& m) {
00160
00161 assert(fSize==m.size());
00162 Mndaxpy(fSize, 1., m.Data(), 1, fData, 1);
00163 return *this;
00164 }
00165
00166 LASymMatrix& operator-=(const LASymMatrix& m) {
00167
00168 assert(fSize==m.size());
00169 Mndaxpy(fSize, -1., m.Data(), 1, fData, 1);
00170 return *this;
00171 }
00172
00173 template<class T>
00174 LASymMatrix& operator+=(const ABObj<sym, LASymMatrix, T>& m) {
00175
00176 assert(fSize==m.Obj().size());
00177 if(m.Obj().Data()==fData) {
00178 Mndscal(fSize, 1.+double(m.f()), fData, 1);
00179 } else {
00180 Mndaxpy(fSize, double(m.f()), m.Obj().Data(), 1, fData, 1);
00181 }
00182
00183 return *this;
00184 }
00185
00186 template<class A, class T>
00187 LASymMatrix& operator+=(const ABObj<sym, A, T>& m) {
00188
00189 (*this) += LASymMatrix(m);
00190 return *this;
00191 }
00192
00193 template<class T>
00194 LASymMatrix& operator+=(const ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T>& m) {
00195
00196 assert(fNRow > 0);
00197 LASymMatrix tmp(m.Obj().Obj());
00198 Invert(tmp);
00199 tmp *= double(m.f());
00200 (*this) += tmp;
00201 return *this;
00202 }
00203
00204 template<class T>
00205 LASymMatrix& operator+=(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, T>, T>, T>& m) {
00206
00207 assert(fNRow > 0);
00208 Outer_prod(*this, m.Obj().Obj().Obj(), m.f()*m.Obj().Obj().f()*m.Obj().Obj().f());
00209 return *this;
00210 }
00211
00212 LASymMatrix& operator*=(double scal) {
00213 Mndscal(fSize, scal, fData, 1);
00214 return *this;
00215 }
00216
00217 double operator()(unsigned int row, unsigned int col) const {
00218 assert(row<fNRow && col < fNRow);
00219 if(row > col)
00220 return fData[col+row*(row+1)/2];
00221 else
00222 return fData[row+col*(col+1)/2];
00223 }
00224
00225 double& operator()(unsigned int row, unsigned int col) {
00226 assert(row<fNRow && col < fNRow);
00227 if(row > col)
00228 return fData[col+row*(row+1)/2];
00229 else
00230 return fData[row+col*(col+1)/2];
00231 }
00232
00233 const double* Data() const {return fData;}
00234
00235 double* Data() {return fData;}
00236
00237 unsigned int size() const {return fSize;}
00238
00239 unsigned int Nrow() const {return fNRow;}
00240
00241 unsigned int Ncol() const {return Nrow();}
00242
00243 private:
00244
00245 unsigned int fSize;
00246 unsigned int fNRow;
00247 double* fData;
00248
00249 public:
00250
00251 template<class T>
00252 LASymMatrix& operator=(const ABObj<sym, LASymMatrix, T>& v) {
00253
00254 if(fSize == 0 && fData == 0) {
00255 fSize = v.Obj().size();
00256 fNRow = v.Obj().Nrow();
00257 fData = (double*)StackAllocatorHolder::Get().Allocate(sizeof(double)*fSize);
00258 } else {
00259 assert(fSize == v.Obj().size());
00260 }
00261
00262 memcpy(fData, v.Obj().Data(), fSize*sizeof(double));
00263 (*this) *= v.f();
00264 return *this;
00265 }
00266
00267 template<class A, class T>
00268 LASymMatrix& operator=(const ABObj<sym, ABObj<sym, A, T>, T>& something) {
00269
00270 if(fSize == 0 && fData == 0) {
00271 (*this) = something.Obj();
00272 (*this) *= something.f();
00273 } else {
00274 LASymMatrix tmp(something.Obj());
00275 tmp *= something.f();
00276 assert(fSize == tmp.size());
00277 memcpy(fData, tmp.Data(), fSize*sizeof(double));
00278 }
00279
00280 return *this;
00281 }
00282
00283 template<class A, class B, class T>
00284 LASymMatrix& operator=(const ABObj<sym, ABSum<ABObj<sym, A, T>, ABObj<sym, B, T> >,T>& sum) {
00285
00286
00287 if(fSize == 0 && fData == 0) {
00288 (*this) = sum.Obj().A();
00289 (*this) += sum.Obj().B();
00290 (*this) *= sum.f();
00291 } else {
00292 LASymMatrix tmp(sum.Obj().A());
00293 tmp += sum.Obj().B();
00294 tmp *= sum.f();
00295 assert(fSize == tmp.size());
00296 memcpy(fData, tmp.Data(), fSize*sizeof(double));
00297 }
00298 return *this;
00299 }
00300
00301 template<class A, class T>
00302 LASymMatrix& operator=(const ABObj<sym, ABSum<ABObj<sym, LASymMatrix, T>, ABObj<sym, A, T> >,T>& sum) {
00303
00304
00305 if(fSize == 0 && fData == 0) {
00306
00307 (*this) = sum.Obj().B();
00308 (*this) += sum.Obj().A();
00309 (*this) *= sum.f();
00310 } else {
00311
00312 LASymMatrix tmp(sum.Obj().B());
00313 tmp += sum.Obj().A();
00314 tmp *= sum.f();
00315 assert(fSize == tmp.size());
00316 memcpy(fData, tmp.Data(), fSize*sizeof(double));
00317 }
00318
00319 return *this;
00320 }
00321
00322 template<class T>
00323 LASymMatrix& operator=(const ABObj<sym, MatrixInverse<sym, ABObj<sym, LASymMatrix, T>, T>, T>& inv) {
00324 if(fSize == 0 && fData == 0) {
00325 fSize = inv.Obj().Obj().Obj().size();
00326 fNRow = inv.Obj().Obj().Obj().Nrow();
00327 fData = (double*)StackAllocatorHolder::Get().Allocate(sizeof(double)*fSize);
00328 memcpy(fData, inv.Obj().Obj().Obj().Data(), fSize*sizeof(double));
00329 (*this) *= inv.Obj().Obj().f();
00330 Invert(*this);
00331 (*this) *= inv.f();
00332 } else {
00333 LASymMatrix tmp(inv.Obj().Obj());
00334 Invert(tmp);
00335 tmp *= double(inv.f());
00336 assert(fSize == tmp.size());
00337 memcpy(fData, tmp.Data(), fSize*sizeof(double));
00338 }
00339 return *this;
00340 }
00341
00342 LASymMatrix& operator=(const ABObj<sym, VectorOuterProduct<ABObj<vec, LAVector, double>, double>, double>&);
00343 };
00344
00345 }
00346
00347 }
00348
00349 #endif // ROOT_Minuit2_LASymMatrix